首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SynchronizationContext和DispatcherUnhandledException

SynchronizationContext和DispatcherUnhandledException
EN

Stack Overflow用户
提问于 2016-01-11 07:13:09
回答 2查看 432关注 0票数 1

我遇到的情况是,UI线程中抛出的异常不会在调用线程中捕获。

代码语言:javascript
复制
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;

namespace SynchronisationContextAndExceptionWPF
{
    public partial class MainWindow : Window
    {
        private readonly SynchronizationContext _synchronizationContext;

        public MainWindow()
        {
            InitializeComponent();

            _synchronizationContext = SynchronizationContext.Current;
        }


        private void Button_OnClick(object sender, RoutedEventArgs e)
        {
            try
            {
                _synchronizationContext.Send(
                    x =>
                    {
                        try
                        {
                            DoSomethingOnUiThreadThatThrowsException();
                        }
                        catch (Exception)
                        {
                            Debug.WriteLine("Catched Exception in thread that threw it.");
                            throw;
                        }
                    }, null);
            }
            catch (Exception)
            {
                Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
                throw;
            }
        }

        private static void DoSomethingOnUiThreadThatThrowsException()
        {
            throw new Exception("Any Exception...");
        }
    }
}

首先,我认为这是不可能的(我找到的所有文档都说我可以捕获那里的异常)。经过一些研究,我发现了这个问题:我的应用程序使用了一个UnhandledExceptionHandler。它处理DispatcherUnhandledException-Event。我正在向用户显示一些信息并设置e.Handled = true;

代码语言:javascript
复制
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;

namespace SynchronisationContextAndExceptionWPF
{
    public partial class App : Application
    {
        public App()
        {
            DispatcherUnhandledException += App_DispatcherUnhandledException;
        }

        private static void App_DispatcherUnhandledException(
            object sender,
            DispatcherUnhandledExceptionEventArgs e)
        {
            Debug.WriteLine("Catched Exception in UnhandledExceptionHandler.");

            // This line makes the difference:
            e.Handled = true;
        }
    }
}

那么,问题是:即使我处理了,为什么DispatcherUnhandledException-Event也会被提出呢?你会如何解决这种情况?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-12 14:30:12

如果您有很多控件,则可以生成一个新的类,该类将处理特殊的异常变量。因此,您只需要更改_synchronizationContext的初始化(希望只在控件的基类中更改一次)。

代码语言:javascript
复制
public partial class MainWindow : Window
{
    private readonly MySynchronizationContext _synchronizationContext;

    public MainWindow()
    {
        InitializeComponent();

        _synchronizationContext = new MySynchronizationContext(SynchronizationContext.Current);

    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            _synchronizationContext.Send(
                x =>
                {
                    DoSomethingOnUiThreadThatThrowsException();
                }, null);
        }
        catch (Exception)
        {
            Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
            throw;
        }
    }

    private static void DoSomethingOnUiThreadThatThrowsException()
    {
        throw new Exception("Any Exception...");
    }
}

class MySynchronizationContext
{
    SynchronizationContext innerContext;

    public MySynchronizationContext(SynchronizationContext ctx)
    {
        innerContext = ctx;
    }

    public virtual void Send(SendOrPostCallback d, object state)
    {
        Exception threadException = null;

        try
        {
            innerContext.Send(_ =>
            {
                try
                {
                    d.Invoke(state);
                }
                catch (Exception exception)
                {
                    threadException = exception;
                }
            }, null);
        }
        catch (Exception ex)
        {

        }

        if (threadException != null)
        {
            throw new Exception("Synchronization error", threadException);
        }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2016-01-11 09:16:24

在lambda表达式中,您可以设置一个异常变量,然后在调用线程中检查该变量。如果设置了它,则在调用线程时抛出异常。

代码语言:javascript
复制
private void button_Click(object sender, RoutedEventArgs e)
    {
        Exception threadException = null;

        try
        {
            _synchronizationContext.Send(
                x =>
                {
                    try
                    {
                        DoSomethingOnUiThreadThatThrowsException();
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Catched Exception in thread that threw it.");
                        threadException = ex;
                        //throw; --> don't throw exception here; otherwise you will get DispatcherUnhandledException twice.
                    }
                }, null);
        }
        catch (Exception)
        {
            Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
            throw;
        }

        if(threadException != null)
        {
            Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
            throw threadException; //throw you previously catched exception here.
        }
    }

你好,丹尼尔

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34715979

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档