當 Task 有未處理的異常時,為什麼我的程序沒有終止?
我正在使用 .NET 4.0 建構 Windows 服務。
我在任務中拋出了各種未處理的異常,但它們不會像 MSDN 文件所述那樣終止我的程序(並行任務- 請參閱未觀察到的任務異常)。
“如果您不給錯誤任務傳播其異常的機會(例如,通過呼叫 Wait 方法),當任務被垃圾收集時,執行時將根據目前的 .NET 異常策略升級任務的未觀察到的異常。”
即使我使用最簡單的任務呼叫,它的行為也是如此:
Task.Factory.StartNew(() => { throw new Exception(); }呼叫該服務時,該服務繼續執行良好。
根據文件,一旦任務被 GC 處理,任務的終結器將重新拋出異常,但這似乎不會發生。MSDN 反复聲明正常的“.NET 異常策略”會導致程序終止。
為什麼這不會終止我的應用程序?我唯一能想到的就是以某種方式引用了某處的任務(它是 lambda 嗎??)
從Essential C# 4.0,第 715 頁,以下內容可能會對您有所幫助:
任務執行期間未處理的異常將被抑制,直到呼叫任務完成成員之一:
Wait()、Result,Task.WaitAll()或Task.WaitAny()。這些成員中的每一個都將拋出任務執行中發生的任何未處理的異常。有很多處理異常的方法。在這裡查看 MSDN。
在回答您的評論時,同一本書的另一句話解釋了為什麼某些異常沒有傳播:
雖然相對罕見,但一般規則(冒泡)的例外之一恰好是在任務上。
$$ .. $$在應用程序退出期間從終結隊列中拋出的任何基於任務的異常都將被抑制。以這種方式設置行為是因為處理此類異常的工作經常過於復雜$$ … $$
為了克服這個問題,一種優雅的方法是創建一個異常處理程序任務並
ContinueWith在任務執行後使用它來跟進。然後,您可以使用parentTask.IsFaulted並優雅地崩潰,即使在應用程序退出期間在終結隊列中拋出異常的情況下也是如此。提示:使用該標誌
OnlyOnFaulted使該任務僅在發生異常時執行。