7

这与上一个问题有关

我现在想了解的是如何防止 UI 线程异常终止应用程序,而非 UI 异常则不能。

作为参考,请参阅此示例

最重要的是,在这种情况下,我希望能够“静默”地终止进程——而不显示询问我是否要发送错误报告的 Windows 对话框。

这是我的 AppDomain UnhandledExceptionHandler:

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{            
    try
    {
        // Maybe do some logging here if allowed
    }
    catch
    {
    }

    // then just terminate the application
    Application.Exit();            
}

更新
鉴于此答案中的评论,我想澄清一下,最重要的是,我想了解更多有关使 UI 线程能够及早通过该Application.ThreadException机制捕获未处理异常的机制的信息。以及这种行为是否可以在非 UI 线程上实现。

4

3 回答 3

8

在 Google 上进行了更多搜索后,我发现这个非常有趣的解释是针对Jeff Atwood 在他的博客中描述的相同问题的。

大家好,很抱歉造成混乱。这种行为实际上是设计,尽管有时设计可能有点复杂。

首先要了解的是,UnhandledException 事件不是未处理的异常“处理程序”。注册事件,与文档所说的相反:-(,不会导致处理未处理的异常。(从那时起它们不会被处理,但我将停止循环推理......)UnhandledException事件只是通知你一个异常没有处理,以防你想在你的线程或应用程序死掉之前尝试保存状态。FWIW,我已经提交了一个错误来修复文档。

更复杂的是,在 v1.0 和 1.1 中,未处理的异常并不总是意味着您的应用程序会死掉。如果未处理的异常发生在主线程或以非托管代码开始其生命周期的线程以外的任何地方,则 CLR 会吃掉异常并允许您的应用程序继续运行。这通常是邪恶的,因为经常会发生的情况是,例如,ThreadPool 线程会一个接一个地默默地死掉,直到您的应用程序实际上没有做任何工作。找出这种失败的原因几乎是不可能的。这可能是 Jeff 认为它之前有效的原因……他总是看到非主线程上的崩溃。

在 v2.0 中,任何线程上的未处理异常都会导致应用程序崩溃。我们发现调试崩溃比调试挂起或上述静默停止工作问题要容易得多。

顺便说一句,在我的 1.1 机器上,来自 MSDN 的示例确实具有预期的输出;只是在您附加调试器(或不附加)之后,第二行才会显示。在 v2 中,我们进行了翻转,以便在调试器附加之前触发 UnhandledException 事件,这似乎是大多数人所期望的。

Jonathan Keljo CLR 异常 PM Jonathan Keljo 于 2005 年 2 月 18 日晚上 10:02

但是,我仍然对 UI 线程如何完成允许您为所有 UI 线程异常拥有一个包罗万象的处理程序的技巧感兴趣。

更重要的是,我对只为我的应用程序禁用 .NET JIT 调试对话框的方法非常感兴趣(而不是为整个机器禁用它,如此处所示

于 2009-08-19T17:50:46.053 回答
3

并不是任何 AppDomain 异常都会终止应用程序,而是未处理的异常(任何类型的)会破坏 AppDomain 并终止应用程序。

这里的问题是您可以在相当高的级别显式处理 UI 线程异常。但是,当您在后台线程中有未处理的异常时,没有办法在同一级别轻松处理它,因此它往往会向上传播并拉下应用程序。Application.ThreadException 至少允许您知道这是导致错误的原因,并在必要时将其记录下来。

UI 线程中未处理的异常会导致同样的事情发生。

于 2009-08-19T17:10:49.177 回答
2

这有帮助吗?

.NET 2.0 中改进的未处理异常行为

此外,这段代码似乎“悄悄地死去”。你在寻找别的东西吗?

using System;

namespace UnhandledException
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;

            throw new NotImplementedException();
        }

        static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception exception = (Exception)e.ExceptionObject;
            System.Console.WriteLine("exception=[" + exception.ToString() + "]");

            Environment.Exit(-1);
        }   
    }
}
于 2009-08-19T17:46:10.230 回答