我在finally块中有一些关键逻辑(带有空的try块),因为我想保证即使线程被中止也会执行代码。但是,我还想检测ThreadAbortException。我发现在try / catch中包装我的关键try / finally块不会捕获ThreadAbortException。有没有办法检测它?
try { try { } finally { // critical logic } } catch(Exception ex) { // ThreadAbortException is not caught here, but exceptions thrown // from within the critical logic are }
答案 0 :(得分:8)
这是一个奇怪的问题。
您发布的代码应该工作。似乎正在进行某种优化,决定不调用你的catch处理程序。
所以,我想用这个来检测异常:
bool threadAborted = true;
try {
try { }
finally { /* critical code */ }
threadAborted = false;
}
finally {
Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");
(我的实际代码只是睡在那个关键的代码部分,所以我可以肯定它会在最终之后中止。)
打印出来:
嗯,确实很奇怪!线程已中止?假
所以我想在那里做更多的工作,欺骗任何“聪明”的优化:
bool threadAborted = true;
try {
try { }
finally { /* critical code */ }
threadAborted = AmIEvil();
}
finally {
Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");
AmIEvil
只是:
[MethodImpl(MethodImplOptions.NoInlining)]
static bool AmIEvil() {
return false;
}
最后打印出来了:
线程已中止?真
你有它。在代码中使用它:
try {
try { }
finally { /* critical code */ }
NoOp();
}
catch (Exception ex) {
// ThreadAbortException is caught here now!
}
NoOp
只是:
[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }
答案 1 :(得分:3)
你可以在catch语句中实际执行ThreadAbortException的代码。问题是一旦执行离开catch块就会重新抛出异常。
如果要实际停止继续异常,可以调用Thread.ResetAbort()。这确实需要完全信任,除非你有一个特定的场景,否则几乎肯定是错误的。
答案 2 :(得分:2)
答案 3 :(得分:2)
我不认为这是可能的。
为什么首先需要处理 ThreadAbortException ?调用 thread.Abort()通常是糟糕设计的标志。有一个标志变量,当设置为true时,只需返回; 来自线程函数,当然要经过适当的清理。
这样你就不必担心异常了。
答案 4 :(得分:2)
如果调用Thread.Abort设计不好,为什么SQL Server会在运行用户代码的线程上调用它?因为这正是查询取消的处理方式,它会导致噩梦。
答案 5 :(得分:0)
我同意arul。 调用Thread.Abort()是糟糕设计的标志。
让我引用MSDN: Thread.Abort的Peter Ritchie(强调是我的):
有很多理由不使用Thread.Abort和ThreadAbortException
在某些平台(如x64和IA64)上,可以在Monitor.Enter和try块(即使使用lock / SyncLock)之前发生中止,使监视器处于孤立状态。 ThreadAbortException可能发生在第三方代码中,而不是为了处理线程中止而编写的。 在.NET 1.x中处理finally块时,可以中止该线程 使用常规控制流逻辑的异常。 异步异常可以中断对分片状态或资源的修改,使它们损坏。
有关详细信息,请参阅:
http://msmvps.com/blogs/peterritchie/archive/2007/08/22/thead-abort-is-a-sign-of-a-poorly-designed-program.aspx
http://www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx
答案 6 :(得分:0)
你尝试过这样的事吗?
try {
try { }
catch (ThreadAbortException)
{
ThreadAbortExceptionBool = true;
}
finally {
// critical logic
if (ThreadAbortExceptionBool)
// Whatever
}
}
catch(Exception ex) {
// ThreadAbortException is not caught here, but exceptions thrown
// from within the critical logic are
}