2014-02-08 100 views
8

我試圖瞭解在任務對象中拋出異常並且從不處理異常。任務未處理的異常

MSDN上有人說:

如果你不上傳播異常的任務,或訪問 其Exception屬性等,除根據 .NET異常策略時升級該任務被垃圾收集。

所以我不太瞭解這些異常以什麼方式影響程序流程。我認爲這些例外一旦被垃圾收集就應該中斷執行。但我無法設計這種行爲。在以下代碼片段中,拋出的異常不會顯示出來。

\\Do something ... 
Task.Run (()=> {throw new Exception("Exception in the task!");}); 
\\Do something else 

請問任何人都可以解釋如何處理未處理的任務異常以及它們如何影響程序流。

+0

看看這裏http://msdn.microsoft.com/en-us/library/dd537614(v=vs.110).aspx – techno

+1

[This will help](http://stackoverflow.com/)問題/ 8803107 /任務和例外 - 沉默?rq = 1) –

+0

@SriramSakthivel謝謝,不是很詳細但有幫助。 – user3101007

回答

18

您正在描述.NET 4.0中的行爲,因爲它是,但您將很難強制垃圾回收並實際觀察該行爲。從Stephen Toub's excelent write-up關於這個問題下面的報價應使其更加明確:「觀察」

任務跟蹤未處理的異常是否已經 在此背景下,「觀察」是指代碼加入 與該任務以某種方式至少被意識到 的例外。這可能是在任務上調用Wait/WaitAll。它在 任務完成後可能正在檢查任務的異常屬性。或者它可能使用任務的結果屬性。 如果某個任務發現其某種特定方式已被觀察到, 生活就很好。但是,如果刪除了對任務的所有引用(使任務可用於垃圾收集),並且如果尚未觀察到它的例外,則該任務知道它的例外 將永遠不會被觀察到。在這種情況下,該任務利用 最終確定,並使用助手對象在終結器線程上傳播未處理的 異常。通過之前描述的行爲 ,終結器線程上的該異常將不受處理,並且 會調用默認的未處理異常邏輯,即記錄 問題並使進程崩潰。

他還建議對異常處理兩個有用的擴展方法「發射後不管」的任務:一個無視例外,另一個立即崩潰的過程:

public static Task IgnoreExceptions(this Task task) 
{ 
    task.ContinueWith(c => { var ignored = c.Exception; }, 
     TaskContinuationOptions.OnlyOnFaulted | 
     TaskContinuationOptions.ExecuteSynchronously | 
     TaskContinuationOptions.DetachedFromParent); 
    return task; 
} 

public static Task FailFastOnException(this Task task) 
{ 
    task.ContinueWith(c => Environment.FailFast(「Task faulted」, c.Exception), 
     TaskContinuationOptions.OnlyOnFaulted | 
     TaskContinuationOptions.ExecuteSynchronously | 
     TaskContinuationOptions.DetachedFromParent); 
    return task; 
} 

在.NET中4.5默認行爲已更改。再次,從another Stephen Toub's post on the subject(感謝Mike z計算它把我的注意力在評論)報價:

爲了讓開發者更容易根據 任務編寫異步代碼,.NET 4.5改變默認的例外行爲不可觀察 例外。雖然未觀察到的異常仍然會導致引發UnobservedTaskException事件(不這樣做將是 重大更改),但默認情況下該進程不會崩潰。相反, 異常最終會在事件發生後被吃掉, 無論事件處理程序是否觀察到異常。儘管如此,這個 行爲可以被配置。

+0

感謝您的詳細解答。 – user3101007

+3

雖然這對於.NET 4是正確的,但在.NET 4.5中,策略已更改爲忽略未查看的任務異常。 –

+0

@mikez感謝您的關注。我已經編輯了相應的答案。 –