假设我们在单独的线程中运行了一些这样的代码:
private static void ThreadFunc() {
ulong counter = 0;
while (true) {
try {
Console.WriteLine( "{0}", counter++ );
}
catch (ThreadAbortException) {
Console.WriteLine( "Abort!" );
}
}
}
调用Thread.Abort()
时,是否可能在catch块之外抛出异常?
答案 0 :(得分:67)
实际上是的,ThreadAbortException
很特别。即使你处理它,它也会在try / catch / finally结束时被CLR自动重新抛出。 (正如评论中所指出的那样,它可以用ResetAbort
来抑制,但到那时代码就像腐烂的鱼一样。)
更不用说即使在try / catch / finally之外没有明显的可执行代码,循环的每次迭代都会在范围之外结束一段时间,因此中止可能发生在try块之外。 / p>
除非你实际上在catch块中做了一些事情,否则我只是试一试/最后不要担心ThreadAbortException
。有一些更好的方法可以在不使用Thread.Abort
的情况下中止线程,这不仅会在不可预测的地点混乱地中断你的代码,而且也不能保证工作,因为如果你的线程当前正在调用一些非托管代码,那么线程就会在控制权返回托管代码之前不会中止。
使用某种类型的同步原语(如ManualResetEvent
)作为一个标志告诉您的线程何时退出会更好。您甚至可以为此目的使用布尔字段,这是BackgroundWorker所做的。
答案 1 :(得分:20)
是。我怀疑您正在询问,因为线程中断仅在线程可能阻止(或者如果它已被阻止)时发生 - 例如对于IO。
对于中止没有这样的保证。它可以在任何时候发生,基本上,虽然有 delay-abort 区域,例如constrained execution regions和catch / finally块,其中中止请求只是被记住,并且线程在它被中止时退出该地区。
同步线程中止(即中止自己的线程)是相当安全的,但异步中止(中止不同的线程)几乎总是一个坏主意。请阅读"Concurrent Programming on Windows" by Joe Duffy以获取更多信息。
编辑:正如下面的Eric所说,中止另一个线程并不能保证实际上也有任何效果。只是引用评论:
如果它离开该区域,我会说该线程被中止,强调
Thread.Abort
完全不可靠。如果循环位于这样的区域中,则因为它被卡在无限循环中而被中止的线程将不会中止。这是Thread.Abort
一个坏主意的另一个原因;如果你不能依靠实际发生的预期效果那么你为什么要调用这个方法?
答案 2 :(得分:6)
实际上, ThreadAbortException 是特殊的,以防它被CLR或 Thread.Abort 方法抛出。比较输出:
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 .
输出:
First Second
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();
}
输出:
First
似乎 Thread的方法在内部调用本机代码,这使得引发的异常特定。
答案 3 :(得分:4)
我不是100%你问的是什么,但我想指出你永远无法吞下ThreadAbortException
:
拨打中止电话时 破坏线程的方法,常见的 语言运行时抛出一个
ThreadAbortException
。ThreadAbortException
很特别 可以捕获的异常 ,但它 将自动再次提升 捕获块结束。
您是否可以通过ThreadAbortException
询问是否可以捕获另一个线程中引发的try/catch
?如果这是你的问题,那么不,你不能。