在线程中抛出的未处理异常不会被捕获

本文关键字:异常 未处理 线程 | 更新日期: 2023-09-27 18:19:03

我正在研究一个使用普通threads实现的项目。应用程序中大多数预期的异常都得到了处理,然而,在某些情况下,其中一个线程抛出了一个意外的异常,应用程序只是崩溃了(应用程序是基于I/OClient-Server的,所以实际上不可能处理所有的异常)。

为了解决这个问题,我试图定义一个全局的UnhandledExceptionHandler,以便应用程序显示一个友好的消息,而不是崩溃。这是我尝试过的:

public partial class App : Application
{
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        AppDomain.CurrentDomain.UnhandledException +=
            new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        // The rest of the startup logic goes here
    }
    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Utilities.DisplayUnhandledException((Exception)e.ExceptionObject);
    }
}

这不起作用。永远不会调用CurrentDomain_UnhandledException。不幸的是,我不能改变应用程序的结构,这意味着我不能使用任务并行库。我不明白为什么这行不通。是否有其他方法来处理线程中抛出的异常?

在线程中抛出的未处理异常不会被捕获

你的方法是正确的。但是,您将无法阻止应用程序终止。

当一个未处理的异常被抛出到你在应用程序中创建的线程时,CurrentDomain_UnhandledException将被调用,允许你记录或报告异常。但是,除非e.IsTerminatingfalse,否则您将无法阻止应用程序的终止。您可以在托管线程中的异常中了解更多有关此行为的信息。

如果您发现CurrentDomain_UnhandledException从未被调用,您应该验证是否调用了Application_Startup来设置处理程序。

如果你仍然有问题,你应该验证Utilities.DisplayUnhandledException没有抛出异常。这也将导致您的申请立即终止。特别是,如果e.ExceptionObject不是Exception类型,将其转换为Exception将抛出异常。但是,在正常情况下,当异常对象不是托管异常时,它将被包装在RuntimeWrappedException中。

为了避免终止应用程序,你需要在线程方法的"堆栈顶部"捕获异常。如果因为无法访问代码而无法做到这一点,那么未处理的异常就是软件有bug的指示,即使发现软件bug很不方便,最好的做法是终止应用程序以避免损坏。