Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以用另一个线程检测挂起的进程并从中恢复吗?_C#_Multithreading_Exception - Fatal编程技术网

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

C# 我可以用另一个线程检测挂起的进程并从中恢复吗?,c#,multithreading,exception,C#,Multithreading,Exception,我有一个偶尔挂起的方法(在dll中我不能修改,但必须使用)。如果我再次运行它,它通常工作正常。我想知道是否可以创建一个后台线程,等待20分钟,然后在我的程序中抛出一个异常 var triesLeft = 5; while (triesLeft > 0) { try { var t = new Thread(() => { wait(20 minutes); throw new ApplicationHungException();}) t.Start();

我有一个偶尔挂起的方法(在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-catch块提供例外情况?

您可以在单独的线程中完成工作,并等待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--;
  }
}

一种方法是在单独的线程中设置错误的方法,并等待两件事情中的一件发生;要么:

  • 线程完成,或者
  • 经过预定的时间量(如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在下面的评论中指出的那样,中止线程是一种危险而脆弱的操作。您的替代方法是允许挂起的线程在其剩余的生命周期内(不管它有多长),或者将Heisenbugy方法调用隔离到一个单独的进程


然而,这又带来了另一个麻烦,因为您必须处理进程间通信、数据序列化和同步。这可能值得,也可能不值得,这是我留给你们的判断。

仅供参考,没有“C#线程”这样的东西。您似乎指的是.NET托管线程。为什么这里需要线程,只需将代码放在“methodthathands”的位置,您就可以理解了exception@IlyaBursov
永远挂起的方法
来自我假设的DLL。是的<代码>永远挂起的方法()位于另一个dll@anthonybell是否可以生成一个线程来运行永远挂起的
方法,并在主线程中等待预先确定的时间,然后检查另一个线程是否仍处于活动状态?本质上是反转哪个线程运行错误的方法,哪个线程负责发出警报。这总是要等待20分钟,还是mre.Set()会导致它中断while循环?@anthonybell the
mre.Set()
会导致它立即中断。@anthonybell这20分钟是它等待的最长时间,然后会重新开始哦,好的。这是有道理的。@anthonybell编辑使用线程池,这对你来说可能更干净,tooThread.Abort真的不是一个好主意-见@ReedCopsey我明白了。让线程在其剩余的(可能是永久的)存在中生存是更好的主意吗?还是有更好的方法来限制线程的寿命?我对多线程没有太多的经验,所以请容忍我。这真的取决于-一般来说,最好是解决问题(防止无限挂起),但线程。中止通常比让线程永远坐在那里更糟糕。。。它可能会导致严重的问题(请参阅该问题中的许多答案),如果它每隔10分钟运行几天,如果我不使用abort()?@anthonybell Yes,我的服务是否最终会被线程填满,而这些线程什么都不做?这就是我提到替代方案的原因。我相信里德的回答也有同样的问题。