ThreadAbortException最终可以跳过吗?

我读过的所有内容声称线程中止将在从ThreadAbortException结束之前执行finally块。 我想确认这一点,以便我可以计划如何处理可以无限期挂起的第三方代码。 但是下面的测试让我困惑:

public void runTest(DateTime deadline) { testThread = new Thread(() => { try { Console.WriteLine("test thread started at " + DateTime.Now.ToShortTimeString()); while (true) { } } finally { Console.WriteLine("test thread entered FINALLY at " + DateTime.Now.ToShortTimeString()); while (true) { } } }); testThread.Start(); while (testThread.IsAlive && deadline.Subtract(DateTime.Now).TotalSeconds > 0) { Console.WriteLine("main thread while loop " + DateTime.Now.ToShortTimeString()); Thread.Sleep(10000); } if (testThread.IsAlive) testThread.Abort(); Console.WriteLine("main thread after abort call " + DateTime.Now.ToShortTimeString()); } 

我在运行时发现的是控制台从未提及进入finally块。 应用程序在.abort调用之后继续,好像根本没有finally块。 难道我做错了什么? 在到达最终写入控制台之前,不应该控制传递给finally块,还是执行顺序仍然是最终在单独的线程中的事实的函数?

文档说ThreadAbortException是一个可以捕获的特殊exception,但它会在catch块的末尾自动再次引发。 引发此exception时,运行时会在结束线程之前执行所有finally块。 因为线程可以在finally块中执行无限制计算或调用Thread.ResetAbort来取消中止,所以无法保证线程将永远结束。

我很确定您的线程被转储,因为您退出方法并丢失对它的引用,因此它被垃圾收集器收集。 尝试将testThread变量作为类的字段成员,看看会发生什么。

那,或者你有一个竞争条件,因为线程并行运行:主线程在spun-up测试线程可以输出最终数据之前完成(例外是昂贵的,需要时间来达到catch或finally块)。

工作线程函数中的finally块在与主线程并行的工作线程上执行。 这是一场竞争。 你不能分清最后的工作线程或者中止调用后的主线程代码。 如果你需要同步中止,那么你必须这样做:

  if (testThread.IsAlive) { testThread.Abort(); bool blnFinishedAfterAbort = testThread.Join(TimeSpan.FromMilliseconds(1000)); if (!blnFinishedAfterAbort) { Console.WriteLine("Thread abort failed."); } } Console.WriteLine("main thread after abort call " + DateTime.Now.ToShortTimeString()); 

请记住,如果您启用了遗留exception处理(请参阅http://msdn.microsoft.com/en-us/library/ms228965.aspx )并且您指定了AppDomain_UnahandledException事件处理程序,那么ThreadAbortException将导致执行到该处理程序BEFORE工作线程函数中的finally块 。 这只是在中止线程时应该注意的令人沮丧和意外执行顺序的另一个例子。

通常不应该跳过finally

控制台应用程序(假设它是一个)可能在finally块运行之前退出(因为在调用Thread.Abort()之后没有等待)。

如果你在程序结束时放置Console.ReadLine()会发生什么?