LegacyUnhandledExceptionPolicy不允许捕捉(吞)ThreadAbortException?不允许、LegacyUnhandledExceptionPolicy、Thread

2023-09-06 16:54:51 作者:归舟放鹤

我使用的是.NET 1.1 compability模式未处理的异常处理。问题是,当LegacyUnhandledExceptionPolicy设置为1(这是我想要什么),我不能赶上和吞咽ThreadAbortException。

I'm using .NET 1.1 compability mode for unhandled exception handling. The problem is that when LegacyUnhandledExceptionPolicy is set to "1" (which is what I want), I cannot catch and swallow ThreadAbortException.

示例code:

App.config中:

App.config:

<configuration>
   <runtime>
      <legacyUnhandledExceptionPolicy enabled="1"/>
   </runtime>
</configuration>

code:

Code:

   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(OFF),上述code燕子ThreadAbortException queitly,符合市场预期。

When legacy exceptions handling is "0" (OFF), the above code swallows ThreadAbortException queitly, as expected.

但是,在原有的异常处理是1上面的code打印ThreadAbortException安慰,这不是我所期望的。

But, when legacy exceptions handling is "1" the above code prints ThreadAbortException to console, which is not what I expect.

任何想法?

感谢。

推荐答案

您不能赶上一个ThreadAbortException,它总是抓后重新提出。有两种基本的解决方案,您的问题。

You cannot catch a ThreadAbortException, it is always re-raised after catching it. There are two basic solutions to your problem.

第一个是您重置中止请求:

First one is that you reset the abort request:

catch (ThreadAbortException) {
    // expected thread abort request, reset it and exit thread
    Thread.ResetAbort();
}

第二个是要解决当您启用旧的异常处理这种情况发生的另一件事。该AppDomain.UnhandledException事件现在也提出了非致命异常。写下您的异常处理程序是这样的:

Second one is to address the other thing that happens when you enable legacy exception handling. The AppDomain.UnhandledException event is now also raised for non-fatal exceptions. Write your exception handler like this:

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

我要推荐的第一个解决方案,你真的不想未处理的终止线程没有留下任何痕迹,在所有异常。

I'd have to recommend the first solution, you really don't want unhandled exceptions that terminate a thread to leave no trace at all.