假设我们在单独的线程中运行了一些这样的代码:
private static void ThreadFunc() {
ulong counter = 0;
while (true) {
try {
Console.WriteLine( "{0}", counter++ );
}
catch (ThreadAbortException) {
Console.WriteLine( "Abort!" );
}
}
}
Run Code Online (Sandbox Code Playgroud)
当Thread.Abort()
被调用时,是有可能的异常catch块之外抛出?
Jos*_*osh 70
实际上是的,a ThreadAbortException
是特别的.即使你处理它,它也会在try/catch/finally结束时被CLR自动重新抛出.(如评论中所述,它可以被抑制,ResetAbort
但到那时,代码闻起来像腐烂的鱼.)
更不用说即使在try/catch/finally之外没有明显的可执行代码,循环的每次迭代都会在范围之外结束一小段时间,因此中止可能发生在try块之外.
除非你实际上在catch块中做了一些事情,否则我只是试一试/最后不要担心ThreadAbortException
.有一些更好的方法可以在不使用的情况下中止线程,Thread.Abort
这不仅会在不可预测的地点混乱地中断你的代码,而且也无法保证工作,因为如果你的线程当前正在调用某些非托管代码,那么线程将不会中止,直到控制返回托管代码.
使用某种类型的同步原语(例如a)ManualResetEvent
作为一个标志告诉你的线程何时退出要好得多.您甚至可以为此目的使用布尔字段,这是BackgroundWorker所做的.
Jon*_*eet 20
是.我怀疑你问的是因为线程中断只发生在一个线程否则会阻塞(或者它已经被阻塞) - 例如对于IO.
中止没有这样的保证.它可以在任何时候发生,基本上,虽然有延迟中止区域,例如约束执行区域和catch/finally块,其中中止请求只是被记住,并且线程在退出区域时中止.
同步线程中止(即中止自己的线程)是相当安全的,但异步中止(中止不同的线程)几乎总是一个坏主意.阅读Joe Duffy的"Windows上的并发编程"以获取更多信息.
编辑:如下面Eric所述,中止另一个线程并不能保证实际上也有任何影响.只是引用评论:
我会说,如果线程退出该区域,该线程将被中止,强调这
Thread.Abort
完全不可靠.如果循环位于这样的区域中,则因为它被卡在无限循环中而被中止的线程将不会中止.这是Thread.Abort
一个坏主意的另一个原因; 如果你不能依靠实际发生的预期效果那么你为什么要调用这个方法呢?
实际上,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();
}
Run Code Online (Sandbox Code Playgroud)
输出:
First
似乎Thread的方法在内部调用本机代码,这使得引发的异常特定.