在 C# 中终止线程
本文关键字:线程 终止 | 更新日期: 2023-09-27 18:36:05
这不是要终止系统进程,而是要杀死"我自己"。我有几个平行的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()
或
Thread.CurrentThread.Abort()?
还是有更好的方法?(我不能使用布尔"停止"变量等"简单"机制,因为"这里的大量代码"非常动态地通过反射等调用其他类。
这甚至有效吗?还是我只是杀死看门狗线程,而不是要监视的线程?
>Thread.Abort
尝试通过注入带外(异步)异常来终止目标线程。这是不安全的,因为异常会在执行序列中不可预测的点注入。由于对数据结构的写入中断,这可能会(并且经常)导致应用程序域中的某种类型的损坏。
Thread.Interrupt
导致BCL中的大多数阻塞调用(如Thread.Sleep
、WaitHandle.WaitOne
等)立即救助。与中止线程不同,中断线程可以完全安全,因为异常是在执行序列中的可预测点注入的。一个狡猾的程序员可以确保这些点被认为是"安全点"。
因此,如果"此处的大量代码"将响应Thread.Interrupt
那么这可能是一种可接受的使用方法。但是,我想引导您更多地转向合作取消模式。基本上,这意味着您的代码必须定期轮询取消请求。TPL已经有一个框架可以通过CancellationToken
来做到这一点。但是,您可以使用ManualResetEvent
或简单的易失性布尔变量轻松完成相同的操作。
"这里有很多代码"不在您的控制之下,或者如果合作取消模式不起作用(可能是因为您使用了错误的第三方库),那么您几乎别无选择,只能启动一个完全独立的进程来运行有风险的代码。使用 WCF 与进程通信,如果它没有响应,则可以在不损坏主进程的情况下终止它。这是很多工作,但这可能是您唯一的选择。
线程处于未知状态时,不建议中止线程。假设线程当前正在执行静态构造函数。静态 ctor 将被中止,并且永远不会再次运行(因为错误的静态 ctor 永远不会再次运行)。您已经有效地破坏了 AppDomain 中的全局状态,而无法恢复。
还有很多其他危险。那只是不会飞。
有两种生产就绪选项中止线程:
- 合作(与 Thread.MemoryBarrier 结合使用设置事件或布尔标志)
- 不要中止线程,而是中止整个 AppDomain 或进程。线程级粒度太小。您需要删除与该线程相关的所有状态,doo。
我想强调的是,你不能以任何其他方式做到这一点。如果您坚持不合作地中止线程,您将在生产中遇到最奇怪的错误。