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

Phi*_*Gan 6 .net c# multithreading

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

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

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

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

如果必须停止某个线程以便进程终止,则将该线程作为后台线程,以便在进程退出时自动终止.

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

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

Bri*_*eon 5

Thread.Abort 由于以下原因,它比以前安全得多。

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

但是,ThreadAbortException在注入的确切时间方面仍然存在问题。考虑这个代码。

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

  public void DoSomething()
  {
    try
    {
      value = DateTime.UtcNow;
    }
    finally
    {
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

可以通过将关键代码放在一个finally块中并使用Constrained Execution Regions来防止这种情况发生,但是除了您定义的最简单的类型之外,要对所有类型都正确是非常困难的。即便如此,你也不能把所有东西都放在一个finally块中。

  • 另一种看待它的方式:由于以下原因,Thread.Abort 比以前少了很多:在非托管代码中延迟中止,而 finally 块执行。如果您因为线程正在执行不需要的工作而中止线程,那么这两件事都会导致线程继续执行不需要的工作。 (5认同)