ThreadAbortException

假设我们有一些像这样的代码在单独的线程中运行:

private static void ThreadFunc() { ulong counter = 0; while (true) { try { Console.WriteLine( "{0}", counter++ ); } catch (ThreadAbortException) { Console.WriteLine( "Abort!" ); } } } 

当调用Thread.Abort() ,是否有可能将exception抛出catch块?

其实是的,一个ThreadAbortException是特殊的。 即使你处理它,它也会在try / catch / finally结束时被CLR自动重新抛出。 (正如在评论中指出的那样,它可以用ResetAbort来压制,但是到那时代码闻起来就像烂鱼。)

更不要说即使try / catch / finally之外没有明显的可执行代码,循环的每一次迭代都会在范围之外停留一段时间,因此中断可能会发生在try块之外。

除非你真的在catch块中做了什么,否则我只是试一试,不要担心ThreadAbortException 。 没有使用Thread.Abort ,有很多更好的方法可以放弃一个线程,它不仅会在一个不可预知的地方混乱地中断你的代码,它也不能保证工作,因为如果你的线程正在调用一些非托pipe的代码,线程将不会中止直到控制权返回到托pipe代码。

使用某种types的同步原语(如ManualResetEvent来作为标志,告诉您的线程何时退出,这会更好。 你甚至可以使用一个布尔型字段来实现这个目的,这就是BackgroundWorker所做的。

是。 我怀疑你是问,因为线程中断只发生在一个线程可能会阻塞(或者如果它已经被阻止) – 例如IO。

没有这种中止的保证。 它基本上可以在任何时候发生,虽然有延迟中止区域,如受约束的执行区域和catch / finally块,中止请求只被记住,并且线程在退出区域时被中止。

同步线程中止(即中止自己的线程)是相当安全的,但asynchronous中止(中止一个不同的线程)几乎总是一个坏主意。 阅读Joe Duffy的“Windows上的并行编程”以获取更多信息。

编辑:正如下面埃里克所指出的,中止另一个线程不保证实际上有任何效果。 只是引用评论:

如果线程退出该区域,我会说线程被中止,强调Thread.Abort是完全不可靠的。 如果循环处于这样一个区域,那么被中止的线程将不会中止。 这是为什么Thread.Abort是一个坏主意的另一个原因; 如果你不能依靠实际发生的效果,那么你为什么要调用这个方法呢?

实际上, ThreadAbortException特别适用于CLR或Thread.Abort方法。 比较输出:

  • Joe Duffy的“Windows上的并行编程”稍微修改了一个例子(添加了Console.WriteLine)。 它通过Thread.CurrentThread.Abort引发exception:
    try { try { Thread.CurrentThread.Abort(); } catch (ThreadAbortException) { Console.WriteLine("First"); //Try to swallow it. } //CLR automatically reraises the exception here . } catch (ThreadAbortException) { Console.WriteLine("Second"); Thread.ResetAbort(); //Try to swallow it again . } //The in - flight abort was reset , so it is not reraised again .
    try { try { Thread.CurrentThread.Abort(); } catch (ThreadAbortException) { Console.WriteLine("First"); //Try to swallow it. } //CLR automatically reraises the exception here . } catch (ThreadAbortException) { Console.WriteLine("Second"); Thread.ResetAbort(); //Try to swallow it again . } //The in - flight abort was reset , so it is not reraised again . 

    输出:

    第一
    第二
    
  • 修改前面的示例以使用不同的ThreadAbortException实例创build方法:
     try { try { // get non-public constructor var cstor = typeof(ThreadAbortException) .GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); // create ThreadAbortException instance ThreadAbortException ex = cstor.Invoke(null) as ThreadAbortException; // throw.. throw ex; } catch (ThreadAbortException) { Console.WriteLine("First"); } } catch (ThreadAbortException) { Console.WriteLine("Second"); Thread.ResetAbort(); } 

    输出:

    第一
    

看起来像Thread的方法在内部调用本地代码,这引起了特定的exception。

我不是100%你问的,但我想指出,你将永远不能吞下一个ThreadAbortException

当调用Abort方法销毁一个线程时,公共语言运行库会抛出一个ThreadAbortExceptionexception。 ThreadAbortException是一个特殊的exception,可以被捕获 ,但是它会在catch块的末尾自动重新引发。

你问是否有可能捕获一个try/catch在另一个线程抛出的ThreadAbortException ? 如果这是你的问题,那么不,你不能。