Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SynchronizationContext和DispatcherUnhandledException_C#_Dispatcher_Synchronizationcontext - Fatal编程技术网

C# SynchronizationContext和DispatcherUnhandledException

C# SynchronizationContext和DispatcherUnhandledException,c#,dispatcher,synchronizationcontext,C#,Dispatcher,Synchronizationcontext,我遇到了这样一种情况:UI线程中抛出的异常不会在调用线程中被捕获 using System; using System.Diagnostics; using System.Threading; using System.Windows; namespace SynchronisationContextAndExceptionWPF { public partial class MainWindow : Window { private readonly Sync

我遇到了这样一种情况:UI线程中抛出的异常不会在调用线程中被捕获

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

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;
        }
    }
}
那么问题是:为什么即使我处理了
dispatchernhandledexception
-事件,也会引发它?
如何解决这种情况?

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

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...");
        }
    }
}
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.
        }
    }
亲切问候,,
Daniel

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


当然这会有用。。。但这意味着我必须记住每次都这样称呼它。。。另外:如果我有一个模块化的软件,其中我有这样工作的控件(并且不知道未处理的ExceptionHandler),它们将不会像预期的那样工作……这对我来说很有用!这也许不是所有人的普遍解决办法,但现在让我很高兴。谢谢