在C#中杀死一个线程

时间:2012-06-01 12:29:30

标签: c# multithreading

这不是关于终止系统进程而是杀死“我自己”。我有几个并行的theads,由于不同的原因可以挂起。

当线程耗时过长时,我已经创建了一个看门狗:

TimerCallback timerDelegate = new TimerCallback(CheckProcessStatus);
System.Threading.Timer watchDogTimer = new Timer(timerDelegate, new ProcessHealth(plog), 1000 * 60, 1000 * 60);
try
   {
   // lots of code here
   } finally
   {
      watchDogTimer.Dispose();
   }

看门狗:

public void CheckProcessStatus(Object timerState) {
    ProcessHealth ph = (ProcessHealth)timerState;
    System.writeLine(string.Format("process runs for {0} minutes!", ph.WaitingTime);
    if (ph.WaitingTime>60) {
      // KILL THE PROCESS
    }
}

当“这里的大量代码”花费的时间过长时,我想终止该线程,无论它处于什么状态。(在“杀死进程”中)。

最好的方法是什么?

Thread.CurrentThread.Interrupt()

OR

Thread.CurrentThread.Abort()?

还是有更好的方法吗? (我不能使用像布尔“停止”变量这样的“简单”机制,因为“这里有很多代码”是非常动态通过反射调用其他类等。

这甚至有用吗?或者我只是杀死看门狗线程,而不是要观看的线程?

2 个答案:

答案 0 :(得分:3)

当一个线程处于未知状态时,它是不可取的。比如说,线程当前正在执行静态构造函数。静态ctor将被中止并且永远不会再次运行(因为错误的静态ctor永远不会再次运行)。您已经有效地破坏了AppDomain中的全局状态,而无法恢复。

还有很多其他危害。那只是不会飞。

有两个生产就绪选择中止线程:

  1. 合作(将事件或布尔标志与Thread.MemoryBarrier结合使用)
  2. 不要中止线程,而是中止整个AppDomain或进程。线程级粒度太小。您需要删除与该线程相关的所有状态,doo。
  3. 我想强调你不能以任何其他方式完成这项工作。如果你坚持不合作地中止线程,你将在生产中遇到最奇怪的错误。

答案 1 :(得分:3)

Thread.Abort尝试通过注入带外(异步)异常来终止目标线程。它是不安全的,因为异常会在执行序列中的不可预测的点处被注入。由于对数据结构的写入中断,这可能(并且经常会)导致应用程序域中的某种类型的损坏。

Thread.Interrupt会导致BCL中的大多数阻止调用(如Thread.SleepWaitHandle.WaitOne等)立即进行救助。与中止线程不同,中断线程可以完全安全,因为异常 在执行序列中的可预测点注入。一个狡猾的程序员可以确保这些点被视为“安全点”。

因此,如果“此处有大量代码”将响应Thread.Interrupt,那么这可能是一种可接受的使用方法。但是,我想引导你更多的合作取消模式。基本上,这意味着您的代码必须定期轮询取消请求。 TPL已经通过CancellationToken建立了一个框架。但是,您可以使用ManualResetEvent或简单的volatile bool变量轻松完成相同的操作。

现在,如果“这里有很多代码”不在您的控制范围内,或者合作取消模式不起作用(可能是因为您使用的是错误的第三方库),那么您几乎别无选择只能旋转运行风险代码的完全独立的过程。使用WCF与进程通信,如果没有响应,则可以在不破坏主进程的情况下终止它。这是很多工作,但它可能是你唯一的选择。