重访Thread.Abort() - 它安全吗?

时间:2011-08-16 15:48:12

标签: c# .net multithreading

关于迁移旧版多线程应用程序的MSDN(来自this页面的线程中的异常处理):

  

通常,更改将暴露以前无法识别的编程问题,以便可以修复它们。但是,在某些情况下,程序员可能已经利用了运行时止回器,例如终止线程。根据具体情况,他们应考虑以下迁移策略之一:

     

重构代码,以便在收到信号时线程正常退出。

     

使用Thread.Abort方法中止线程。

     

如果必须停止某个线程以便可以继续进程,请将该线程作为后台线程,以便在进程退出时自动终止。

     

在所有情况下,策略都应遵循例外的设计指南。请参阅例外设计指南。

这表明使用Thread.Abort是终止线程的合适方法。我不看的时候有什么变化吗?我听到的最后一次是因为这可能导致意外行为所以不应该使用。

3 个答案:

答案 0 :(得分:4)

由于以下原因,

Thread.Abort比过去安全得多。

  • 当执行处于非托管代码时,运行时将推迟中止。
  • 中止将允许finally块执行。

但是,ThreadAbortException注入的确切时间仍然存在问题。考虑一下这段代码。

public class Example
{
  private DateTime value = DateTime.MinValue;

  public void DoSomething()
  {
    try
    {
      value = DateTime.UtcNow;
    }
    finally
    {
    }
  }
}

如果此代码在32位平台上运行,value变量可能会被破坏,如果Thread.Abort被调用且ThreadAbortException在写入value的过程中被注入DateTime 1}}。由于finally是8个字节,因此必须使用多个指令进行写入。

可以通过将关键代码放在finally块中并使用Constrained Execution Regions来防止这种情况发生,但除了您定义的最简单类型之外,所有这些都非常困难。即便如此,您也不能将所有放在{{1}}块中。

答案 1 :(得分:1)

一般来说,Thread.Abort会杀死线程,使当时处理的数据处于未知状态。状态未知,处理该数据通常不安全。但是,当您尝试终止进程时,您不再期望再处理该线程的数据,那么为什么不中止呢?

答案 2 :(得分:1)

好吧,Thread.Abort()的问题在于可能会在工作中间中止线程。这可能会导致您的州被破坏。这就是为什么建议使用volatile bool标志来控制线程,并让线程优雅地完成它的任务,但是基于那个标志。

有关详细信息,我记得this blog post