LegacyUnhandledExceptionPolicy不允许捕获(和忽略)ThreadAbortException?

5
我使用.NET 1.1兼容模式处理未处理的异常。问题在于,当LegacyUnhandledExceptionPolicy设置为“1”(这是我想要的),我无法捕获和忽略ThreadAbortException。
示例代码:
App.config:
<configuration>
   <runtime>
      <legacyUnhandledExceptionPolicy enabled="1"/>
   </runtime>
</configuration>

代码:

   class Program {

      static void Main(string[] args) {
         AppDomain.CurrentDomain.UnhandledException += _onBackgroundThreadCrash;
         var t = new Thread(_worker) { IsBackground = true };
         t.Start();
         Thread.Sleep(1000);
         t.Abort();
         Console.ReadLine();
      }

      private static void _worker() {
         try {
            while (true);
         } catch (ThreadAbortException) { 
            // expected thread exit, don't rethrow
         }
      }

      private static void _onBackgroundThreadCrash(object sender, UnhandledExceptionEventArgs e) {
         Console.WriteLine(e.ExceptionObject as Exception);
      }

   }

当遗留异常处理设置为“0”(关闭)时,上述代码会如预期地静默处理ThreadAbortException。
但是,当遗留异常处理设置为“1”时,上述代码会将ThreadAbortException打印到控制台,这不是我期望的结果。
有什么想法吗?
谢谢。
1个回答

6
您无法捕获ThreadAbortException,捕获后它总是被重新抛出。有两种基本的解决方案。
第一种方法是重置中止请求。
catch (ThreadAbortException) {
    // expected thread abort request, reset it and exit thread
    Thread.ResetAbort();
}

第二个问题是针对启用传统异常处理时发生的其他情况。现在,非致命异常也会引发AppDomain.UnhandledException事件。请按照以下方式编写您的异常处理程序:

private static void _onBackgroundThreadCrash(object sender, UnhandledExceptionEventArgs e) {
    if (e.IsTerminating) {
        Console.WriteLine(e.ExceptionObject as Exception);
    }
}

我建议采用第一种解决方案,因为你真的不想让未被处理的异常终止线程而没有任何痕迹。


谢谢,这一切都很有道理。我仍然想知道为什么当LegacyUnhandledExceptionPolicy=0时,我的处理程序在出现ThreadAbortException时不被调用? - Borka
这只是.NET 2.0中异常处理策略变更的一部分,AppDomain.UnhandledException仅在终止应用程序的异常情况下被引发。 - Hans Passant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接