我可以使用另一个线程检测挂起的进程并从中恢复吗?

时间:2013-10-11 23:10:03

标签: c# multithreading exception

我有一种偶尔会挂起的方法(在dll中我无法修改但必须使用)。如果我再次运行它通常会正常工作。我想知道是否有可能使后台线程等待20分钟,然后在我的程序中抛出异常。

var triesLeft = 5;
while (triesLeft > 0) {
  try {
    var t = new Thread(() => { wait(20 minutes); throw new ApplicationHungException();})
    t.Start();
    Object o = MethodThatHangsForever10PercentOfTheTime();
  } catch (ApplicationHungException e) {
    triesLeft--;
  }
}
t.Abort();

这不起作用,因为异常没有传递给它包含的try catch块。有没有办法可以让线程给try块提供异常?

2 个答案:

答案 0 :(得分:2)

执行此操作的一种方法是在单独的线程中引发错误的方法,并等待两件事之一发生;之一:

  • 线程完成,或
  • 经过预定时间量(例如20分钟)

一旦发生这些事情,我们就可以采取适当的行动。

代码看起来像这样:

static void DoProcessing() {
    var triesLeft = 5;
    Object o = null;

    while (triesLeft > 0) {
        var t = new Thread(() => { o = MethodThatHangsForever10%OfTheTime(); }).Start();
        if (t.Join(new TimeSpan(0, 20, 0))) {
            // The thread completed
            break;
        } else {
            // We're out of time.
            t.Abort(); // Important: See comments below about this
            triesLeft--;
        }
    }
}

事实证明,正如Reed Copsey在下面的评论中指出的那样,中止线程是一种冒险且脆弱的操作。您的替代方案是允许挂起的线程在其余生中生存(无论多长时间),或者将Heisenbuggy方法调用隔离到单独的进程。

然而,这开辟了另一种蠕虫,因为您必须处理进程间通信,数据序列化和同步。这可能是也可能不值得,这是我留给你的判断电话。

答案 1 :(得分:1)

您可以在单独的线程中完成工作,并等待20分钟才能完成:

var triesLeft = 5;
while (triesLeft > 0) 
{
    var mre = new ManualResetEvent(false);

    ThreadPool.QueueUserWorkItem(_ => {
                           MethodThatHangsForever10PercentOfTheTime();
                           mre.Set();
                     });

    if (mre.WaitOne(TimeSpan.FromMinutes(20)))
    {
          break; // Success!
    }
    triesLeft--;
  }
}