假设我们有一些像这样的代码在单独的线程中运行:
private static void ThreadFunc() {
ulong counter = 0;
while (true) {
try {
Console.WriteLine( "{0}", counter++ );
}
catch (ThreadAbortException) {
Console.WriteLine( "Abort!" );
}
}
}
当调用
Thread.Abort()
时,是否有可能在catch块之外抛出异常?
ThreadAbortException
很特别。即使你处理了它,它也会在 try/catch/finally 结束时被 CLR 自动重新抛出。 (正如评论中所指出的,它可以用 ResetAbort
来抑制,但到那时代码闻起来像烂鱼。)
更不用说,即使在 try/catch/finally 之外没有明显的可执行代码,循环的每次迭代都会在短时间内超出范围,因此中止可能会在 try 块之外发生。
除非你实际上在 catch 块中做一些事情,否则我只会尝试/最后,而不用担心
ThreadAbortException
。有很多更好的方法可以在不使用 Thread.Abort
的情况下中止线程,这不仅会在不可预测的点上混乱地中断您的代码,而且也不能保证它能正常工作,因为如果您的线程当前正在调用某些非托管代码,则该线程将不会中止直到控制权返回到托管代码。
ManualResetEvent
)作为告诉线程何时退出的标志。您甚至可以使用布尔字段来达到此目的,这就是BackgroundWorker 所做的。
是的。我怀疑你问这个问题是因为线程中断仅在线程可能阻塞(或者它已经被阻塞)时发生 - 例如对于 IO。
没有这样的中止保证。基本上,它可以在任何时候发生,尽管存在“延迟中止”区域,例如“约束执行区域”和 catch/finally 块,其中中止请求只是被记住,并且线程在退出该区域时中止。 同步线程中止(即中止您自己的线程)相当安全,但异步中止(中止不同的线程)几乎总是一个坏主意。阅读 Joe Duffy 所著的 “Windows 上的并发编程” 了解更多信息。
编辑:正如下面 Eric 所指出的,中止另一个线程也不能保证实际上有任何效果。只是引用评论: 我会说,如果退出该区域,线程就会中止,强调
Thread.Abort
是完全不可靠的。如果循环位于这样的区域,则由于陷入无限循环而被中止的线程将不会中止。这也是
Thread.Abort
是一个坏主意的另一个原因;如果您不能依赖实际发生的预期效果那么为什么要调用该方法?方法抛出的。比较输出:实际上,
ThreadAbortException是特殊的,如果它是由CLR或Thread.Abort
稍微修改了 Joe Duffy 的“Windows 上的并发编程”示例(添加了 Console.WriteLine)。它通过 Thread.CurrentThread.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 .
输出:
第一
第二
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的方法在内部调用本机代码,这使得引发的异常变得特定。
ThreadAbortException
当调用 Abort 时
销毁线程的方法,常见的
语言运行时抛出
ThreadAbortException
。
ThreadAbortException
是一个特殊的 可以捕获的异常,但是它 将自动再次提高 catch 块的末尾。您是否在问是否可以捕获用在另一个线程中抛出的ThreadAbortException
try/catch
? 如果这是你的问题,那么不,你不能。