2013-06-25 37 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 
     } 

    }