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

sha*_*874 1 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

_devicePlugWatcher = new ManagementEventWatcher(pluggedQueryStr);
_devicePlugWatcher.EventArrived += (DevicePluggedEventReceived);
Run Code Online (Sandbox Code Playgroud)

mm8*_*mm8 5

如果在非线程池线程(或非线程)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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并将其与异常发生在未观察到的内部的情况进行比较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);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你也应该处理TaskScheduler.UnobservedTaskException。