为什么AppDomain.CurrentDomain.UnhandledException没有捕获来自非UI线程的未处理异常?

时间:2018-01-22 21:34:46

标签: c# wpf

我已经阅读了一些其他线程和文章,建议有一种方法可以捕获源自非UI线程的未处理异常。出于某种原因,这对我不起作用。正在捕获未处理的UI异常。即使我通过从非UI线程中抛出异常进行测试,CurrentDomainUnhandledException也不会执行。

更奇怪的是,非UI线程上的异常并没有像我想象的那样关闭应用程序。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Application.Current.DispatcherUnhandledException += CurrentDispatcherUnhandledException;

        AppDomain.CurrentDomain.UnhandledException +=
               CurrentDomainUnhandledException;
    }

    void CurrentDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {
        e.Handled = true;
        MessageBox.Show(e.Exception.Message, "Caught an unhandled exception!");
    }

    void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Exception ex = e.ExceptionObject as Exception;
        MessageBox.Show(ex.Message, "Uncaught Thread Exception",
                        MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

我从处理插入设备的事件处理程序中抛出,这绝对不是UI线程。调试器中断并向我显示异常未处理的消息。然而,当我继续应用程序继续运行并似乎继续工作。我为此感到困惑。

_devicePlugWatcher = new ManagementEventWatcher(pluggedQueryStr);
_devicePlugWatcher.EventArrived += (DevicePluggedEventReceived);

1 个答案:

答案 0 :(得分:2)

如果在非线程池线程(或非AppDomain.CurrentDomain.UnhandledException)上抛出异常,则应调用Task事件处理程序。试试这个例子:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;

        Thread thread = new Thread(() => 
        {
            Thread.Sleep(5000);
            throw new Exception("test");
        });
        thread.Start();
    }

    void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Exception ex = e.ExceptionObject as Exception;
        MessageBox.Show(ex.Message, "Uncaught Thread Exception",
                        MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

并将其与非观察Task内发生异常的情况进行比较:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

        Task.Run(() =>
        {
            throw new Exception("test");
        });

        Loaded += (s, e) => 
        {
            //gc so the unobserved exception "bubbles" up
            GC.Collect(3, GCCollectionMode.Forced, true);
        };
    }

    private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        Exception ex = e.Exception;
        MessageBox.Show(ex.Message, "Uncaught Thread Exception",
                        MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

所以你也应该处理TaskScheduler.UnobservedTaskException