【发布时间】:2010-08-23 22:07:16
【问题描述】:
我想从另一个线程监视一个线程。当前正在查看 threasd.isalive 属性。如果线程中有任何异常,仍然 thread.isalive 属性为 true。
如果线程有任何异常或线程处于无限循环中,我想杀死线程..
会感谢您的意见/解决方案/建议。
拉朱
【问题讨论】:
标签: .net
我想从另一个线程监视一个线程。当前正在查看 threasd.isalive 属性。如果线程中有任何异常,仍然 thread.isalive 属性为 true。
如果线程有任何异常或线程处于无限循环中,我想杀死线程..
会感谢您的意见/解决方案/建议。
拉朱
【问题讨论】:
标签: .net
听起来受监控的线程正在捕获它抛出的异常,否则,它会终止并且可能还会中断整个进程。您可以订阅AppDomain.FirstChanceException 事件来确定最初抛出异常的时间,但即使发生这种情况,您也不一定要杀死线程(如果线程捕获异常,处理它并正常进行怎么办? ?)。相反,请考虑让异常“正常”终止线程,然后在您的监控代码中捕获它以防止它取消进程。
无法判断线程是否处于无限循环中,但您可以终止运行时间过长的线程(参见下面的示例代码)。但是,使用Thread.Abort 强制终止线程可能会导致问题并且是代码异味(请参阅here)。您应该考虑更改工作线程以管理自己的生命周期。
class Program
{
static void Main(string[] args)
{
if (RunWithTimeout(LongRunningOperation, TimeSpan.FromMilliseconds(3000)))
{
Console.WriteLine("Worker thread finished.");
}
else
{
Console.WriteLine("Worker thread was aborted.");
}
}
static bool RunWithTimeout(ThreadStart threadStart, TimeSpan timeout)
{
Thread workerThread = new Thread(threadStart);
workerThread.Start();
bool finished = workerThread.Join(timeout);
if (!finished)
workerThread.Abort();
return finished;
}
static void LongRunningOperation()
{
Thread.Sleep(5000);
}
}
【讨论】:
通常这是过度设计的标志。绝大多数程序根本不需要这个。
如果您真的需要检测线程中的无限循环,那么您应该将线程逻辑构建在一个主循环中并将其“签入”到一个看门狗 .主循环当然是无限的(除非线程应该“结束”),但这会捕获任何嵌套在主循环中的无限循环。
问题是:这个“看门狗”是什么?
它不能是同一个 AppDomain 中的另一个线程。在这种情况下Thread.Abort一个线程是完全不合适的。
它可能是一个单独的 AppDomain 中的线程。就个人而言,我对 AppDomain 回收期间发生的“尽力而为但不保证”的清理方式并不完全满意,因此我完全避免使用多个 AppDomain。
这可能是一个过程。这种解决方案在非常重要的自动化解决方案中相当普遍。
它也可以是另一台计算机。该解决方案用于关键自动化解决方案。我过去所做的大部分工作都涉及到每台计算机上的看门狗进程,以及提供一种热备份故障转移集群的看门狗计算机。
不过,我可以坦率地说,98% 的时间都会问这个问题,答案是“首先要确保你没有在线程中放置无限循环”。换句话说,设计和实施看门狗解决方案的巨大成本根本不在实际需求的范围内。设计和代码审查与良好的测试策略相结合通常是最佳解决方案。
【讨论】: