Application.ThreadException 和 AppDomain.CurrentDomain.UnhandledException 有啥区别?

Posted

技术标签:

【中文标题】Application.ThreadException 和 AppDomain.CurrentDomain.UnhandledException 有啥区别?【英文标题】:What's the difference between Application.ThreadException and AppDomain.CurrentDomain.UnhandledException?Application.ThreadException 和 AppDomain.CurrentDomain.UnhandledException 有什么区别? 【发布时间】:2011-01-02 03:24:34 【问题描述】:

好吧,这很简单:

Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException 有什么区别?

我需要同时处理这两个问题吗?

谢谢!

【问题讨论】:

【参考方案1】:

Application.ThreadException 特定于 Windows 窗体。 Winforms 运行事件处理程序以响应 Windows 发送给它的消息。以 Click 事件为例,我相信你知道它们。如果这样的事件处理程序引发异常,则 Winforms 消息循环内有一个后挡块来捕获该异常。

该支持触发Application.ThreadException 事件。如果您不覆盖它,用户将获得ThreadExceptionDialog。这使他可以忽略异常并继续运行您的程序。顺便说一句,这不是一个好主意。

您可以通过在 Program.cs 的 Main() 方法中调用 Application.SetUnhandledExceptionMode() 来禁用此行为。如果没有该支持,当线程死于未处理的异常时,通常会发生这种情况:AppDomain.UnhandledException 触发并且程序终止。

Fwiw:“ThreadException”是一个非常糟糕的名称选择。它与线程无关。

【讨论】:

以及如何阻止 WinForms 应用程序在出现Application.ThreadException 时崩溃。我用我的小 C# 代码对此[here] 提出了一个问题。 鉴于 winforms 绑定到单个线程,我总是将其视为应用程序线程异常。【参考方案2】:

来自source:

在使用 Windows 窗体的应用程序中,未处理的异常 主应用线程导致 Application.ThreadException 要提出的事件。如果处理此事件,则默认行为是 未处理的异常不会终止应用程序, 尽管应用程序处于未知状态。在这种情况下, 未引发 UnhandledException 事件。这种行为可以 通过使用应用程序配置文件或使用 Application.SetUnhandledExceptionMode 方法将模式更改为 UnhandledExceptionMode.ThrowExceptionThreadException 之前 事件处理程序已连接。这仅适用于主应用程序 线。 UnhandledException 事件引发未处理 其他线程中抛出的异常。

Visual Studio 2005 开始,Visual Basic 应用程序 框架为主要的未处理异常提供了另一个事件 应用程序线程 - WindowsFormsApplicationBase.UnhandledException。 此事件有一个与事件同名的事件参数对象 AppDomain.UnhandledException 使用的事件参数对象,但具有 不同的属性。特别是,此事件参数对象具有 允许应用程序继续的ExitApplication 属性 运行,忽略未处理的异常(并离开应用程序 处于未知状态)。在这种情况下,AppDomain.UnhandledException 未引发事件。

Application.ThreadException 可以被捕获并且应用程序可以继续(通常不是一个好主意,但对于像定期运行一些操作这样的应用程序来说,这是一个很好的解决方案)。

要捕获不是由 Windows 窗体创建和拥有的线程中发生的异常,请使用 AppDomain.UnhandledException。它允许应用程序在系统默认处理程序向用户报告异常并终止应用程序之前记录有关异常的信息。处理此异常不会阻止应用程序被终止。 可以做到的最大(程序数据可能会在不处理异常时损坏)是保存程序数据以供以后恢复。之后,应用程序域被卸载并且应用程序终止。

.NET 4 开始,不会针对异常引发此事件 破坏进程的状态,例如堆栈溢出或 访问冲突,除非事件处理程序是安全关键的并且 具有HandleProcessCorruptedStateExceptionsAttribute 属性。

更多详情请见MSDN。

【讨论】:

【参考方案3】:

好的 - 我面前有它,msdn 的这段代码非常不言自明:

public static void Main(string[] args)

    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new 
        ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

    // Set the unhandled exception mode to force all Windows Forms 
    // errors to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    // Runs the application.
    Application.Run(new ErrorHandlerForm());

【讨论】:

这与 serhio 的另一个答案相反,他说: UnhandledExceptionMode.ThrowException 应该在 ThreadException 事件处理程序连接之前设置。不确定订单是否真的很重要...... @DavidePiras 是的,还有一些更模糊的东西。在我的情况下,SetUnhandledException 似乎没有什么区别。【参考方案4】:

问题是,ThreadException 是由于您的线程出现问题而发生的,如果您的代码抛出未处理的异常,则会触发 Unhandled Exception

导致第二种情况的最简单方法是创建一个没有 try...catch 块的应用程序并抛出异常。

现在,如果您需要保险,您可以同时处理它们,但是如果您正确捕获和处理您的 exceptions,那么您不应该需要 UnhandledException 处理程序,因为它有点像包罗万象。

【讨论】:

谢谢 - 我不太清楚的是,如果处理 UnhandledException 我也会捕获 ThreadException - 似乎不是这样

以上是关于Application.ThreadException 和 AppDomain.CurrentDomain.UnhandledException 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章