1.Task.Factory.StartNew(() =>2.{3.throw new Exception();4.});事實上此時Task的異常處於未覺察狀態,這個未覺察狀態的異常會在垃圾回收時終結器執行線程中被拋出。
為了誘發這個異常,我們可以通過GC.Collect來強制垃圾回收從而引發終結器處理線程,此時Task的未覺察異常會被拋出。
01.//在Task中拋出異常02. 03.Task.Factory.StartNew(() =>04.{05.throw new Exception();06.});07. 08. 09.//確保任務完成10.Thread.Sleep(100);11.//強制垃圾會受到12.GC.Collect();13.//等待終結器處理14.GC.WaitForPendingFinalizers();OK,異常拋出,程序崩潰,如下輸出:
Unhandled Exception: System.AggregateException: A Task's exception(s) were not
bserved either by Waiting on the Task or accessing its Exception property. As a
result, the unobserved exception was rethrown by the finalizer thread. ---> Sys
em.Exception: Exception of type 'System.Exception' was thrown.
at Mgen.Program.<Main>b__0() in E:\Users\Mgen\Documents\Visual Studio 2010\P
ojects\Mgen\Mgen\Program.cs:line 19
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of inner exception stack trace ---
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
我們可以通過調用Task.Wait/WaitAll,或者引用Task<T>.Result屬性,或者最簡單的引用Task.Exception屬性來使Task的異常被覺察。
比如這樣通過Task.Wait手動捕獲AggregateException:
01.try02.{03.Task.WaitAll(04.Task.Factory.StartNew(() =>05.{06.throw new Exception();07.}));08.}09.catch (AggregateException)10.{ }11. 12.//確保任務完成13.Thread.Sleep(100);14.//強制垃圾會受到15.GC.Collect();16.//等待終結器處理17.GC.WaitForPendingFinalizers();當然最簡單的就是直接引用一下Task.Exception屬性:
注意這裡使用Task.ContinueWith是為了避免直接引用Task變量,這樣垃圾回收可以處理這個Task對象!
01.//使用Task.ContinueWith可以避免直接引用Task變量,這樣垃圾回收可以處理這個Task對象!02. 03.Task.Factory.StartNew(() =>04.{05.throw new Exception();06.}).ContinueWith(t => { var exp = t.Exception; });07. 08.//确保任务完成09.Thread.Sleep(100);10.//强制垃圾会受到11.GC.Collect();12.//等待终结器处理13.GC.WaitForPendingFinalizers();另外,可以通過TaskContinuationOptions.OnlyOnFaulted來使引用Exception屬性只發生在發生異常時(即Exception為null的時候沒必要再去引用它),代碼:
1.Task.Factory.StartNew(() =>2.{3.throw new Exception();4.}).ContinueWith(t => { var exp = t.Exception; }, TaskContinuationOptions.OnlyOnFaulted);通過UnobservedTaskExceptionEventArgs.SetObserved方法來將異常標記為已覺察。
代碼:
01.最后是TaskScheduler.UnobservedTaskException事件,该事件是所有未觉察异常被抛出前的最后可以将其觉察的方法。通过UnobservedTaskExceptionEventArgs.SetObserved方法来将异常标记为已觉察。02. 03.代码:04. 05.TaskScheduler.UnobservedTaskException += (s, e) =>06.{07.//設置所有未覺察異常被覺察08.e.SetObserved();09.};10. 11.Task.Factory.StartNew(() =>12.{13.throw new Exception();14.});15. 16.//確保任務完成17.Thread.Sleep(100);18.//強制垃圾會受到19.GC.Collect();20.//等待終結器處理21.GC.WaitForPendingFinalizers();
OK,沒有異常拋出。
沒有留言:
張貼留言