我有一种偶尔会挂起的方法(在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块提供异常?
答案 0 :(得分:2)
执行此操作的一种方法是在单独的线程中引发错误的方法,并等待两件事之一发生;之一:
一旦发生这些事情,我们就可以采取适当的行动。
代码看起来像这样:
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--;
}
}