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方法销毁一个线程时,公共语言运行库会抛出一个
ThreadAbortException
exception。ThreadAbortException
是一个特殊的exception,可以被捕获 ,但是它会在catch块的末尾自动重新引发。
你问是否有可能捕获一个try/catch
在另一个线程抛出的ThreadAbortException
? 如果这是你的问题,那么不,你不能。