2013-06-25 36 views
2

下面的示例简化了我的问题。在新线程中引发异常。如果我没有在线程内处理它,它不会被外部try/catch捕获并崩溃我的应用程序。在不同线程中捕获异常

有什么办法可以保证我发现任何异常。

 try 
     { 
      new Thread(delegate() 
       { 
        throw new Exception("Bleh"); // <--- This is not caught 

       }).Start(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 

回答

5

一般来说,在线程本身内捕获异常是最容易的。

但是,如果你想从线程函数本身(如果你可以使用Task,而不是旧Thread的方法),你可以写这样的代码分别捕捉到了异常:

var task = Task.Factory.StartNew(() => 
{ 
    throw new Exception("Test"); 
}); 

task.ContinueWith(t => handleException(t.Exception), TaskContinuationOptions.OnlyOnFaulted); 

它使用ContinueWith()调用另一个方法的第一个线程已经完成,并发生异常后,这样你就可以登录异常或什么:

static void handleException(AggregateException exception) 
{ 
    foreach (var ex in exception.Flatten().InnerExceptions) 
     Console.WriteLine(ex.Message); 
} 

这并不是真的让你解决任何东西 - 在上明智的做法是在线程函数本身中正确处理异常。

+0

非常好的方式来处理它。 –

1

使用AppDomain.UnhandledExceptionApplication.ThreadExceptionDispatcher.UnhandledException。这取决于应用程序的实际类型。

另一种可能性是使用AOP(想到PostSharp)。但是,捕捉例外并不是唯一的目标。您需要找到解决异常原因的方法。如果它是一个错误,这个例外是有用的,并且记录足够。如果有更复杂的原因需要考虑并采取对策。不幸的是,没有“通用解决方案”。所以如果你没有预先捕捉异常,我怀疑你可以采取行动。

+0

这使我可以记录异常,但异常仍然通过并崩溃应用程序。 – CathalMF

+0

是的,我知道我应该在线程本身捕捉异常,但在更复杂的开发中,我可能会错过某些东西,而且我不想因为我忘记了try/catch而导致整个系统崩溃。 – CathalMF

+2

那么,有错误的应用程序会崩溃。您无法做任何事情,因为发生异常之后,应用程序可能处于未知状态。那么你会怎么做?为了防止它崩溃,还有其他的手段:单元测试,调试,日志记录,... – JeffRSon

2

我这样说吧,我相信这是最安全:

var thread = new Thread(MyMethod); 
thread.start(); 

这种方法。 try-catch应该在任何线程内

private void MyMethod() 
{ 
    try 
    { 
     { 
      throw new Exception("Bleh");//<--- This's not caught => now it is caught :) 
     } 
    } 
    catch (Exception ex) 
    { 
     Logger.Log(ex.ToString()); 
    } 
} 
+0

是的,这是正确的方法来做到这一点,但即时通讯尝试弄清楚几乎有一个全球性的渔获。 – CathalMF

0

在我的理解.net不允许在两个线程之间进行通信。因为线程彼此隔离。你可以以简单的方式实现这一点,我不知道它会适合你多少。如果有用,请标记答案。

public Exception exception; 

private void button1_Click(object sender, EventArgs e) 
{ 
     try 
     { 
      new Thread(delegate() 
      { 
       try 
       { 
        throw new Exception("Bleh"); // <--- This is not caught 
       } 
       catch (Exception e) 
       { 
        exception = e; 
       } 

      }).Start(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 

     if (exception != null) 
     { 
      //your code here 
     } 

    }