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.
try
02.
{
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,沒有異常拋出。
沒有留言:
張貼留言