[英]What is the proper way to propagate exceptions in continuation chains?
在連續鏈中傳播異常的正確方法是什么?
t.ContinueWith(t2 =>
{
if(t2.Exception != null)
throw t2.Exception;
/* Other async code. */
})
.ContinueWith(/*...*/);
t.ContinueWith(t2 =>
{
if(t2.IsFaulted)
throw t2.Exception;
/* Other async code. */
})
.ContinueWith(/*...*/);
t.ContinueWith(t2 =>
{
if(t2.Exception != null)
return t2;
/* Other async code. */
})
.ContinueWith(/*...*/);
t.ContinueWith(t2 =>
{
if(t2.IsFaulted)
return t2;
/* Other async code. */
})
.ContinueWith(/*...*/);
t.ContinueWith(t2 =>
{
t2.Wait();
/* Other async code. */
})
.ContinueWith(/*...*/);
t.ContinueWith(t2 =>
{
/* Other async code. */
}, TaskContinuationOptions.NotOnFaulted) // Don't think this one works as expected
.ContinueWith(/*...*/);
TaskContinuationOptions.OnlyOn...
可能會有問題,因為如果不滿足條件,它們會導致延續取消 。 在我理解之前,我在編寫的代碼中遇到了一些微妙的問題。
像這樣的鏈式延續實際上很難做到。 到目前為止,最簡單的解決方法是使用新的.NET 4.5 await
功能。 這使您幾乎可以忽略您正在編寫異步代碼的事實。 您可以像使用同步等效塊一樣使用try / catch塊。 對於.NET 4,可以使用異步定位包 。
如果您使用的是.NET 4.0,最簡單的方法是從每個延續中的前導任務訪問Task.Result
,或者,如果它不返回結果,請使用Task.Wait()
就像在示例代碼中一樣。 但是,您可能最終會得到一個嵌套的AggregateException
對象樹,稍后您需要解析這些對象才能獲得“真正的”異常。 (同樣,.NET 4.5使這更容易。當Task.Result
拋出AggregateException
, Task.GetAwaiter().GetResult()
- 否則等效 - 拋出基礎異常。)
如果您不希望在發生異常(即日志記錄)時特別執行任何操作,並且只希望傳播異常,則只需在拋出異常時(或在取消時)運行continuation。
task.ContinueWith(t =>
{
//do stuff
}, TaskContinuationOptions.OnlyOnRanToCompletion);
如果您明確要處理異常的情況(可能要進行日志記錄,請將拋出的異常更改為其他類型的異常(可能包含其他信息,或隱藏不應公開的信息))然后您可以添加使用OnlyOnFaulted
選項的延續(可能除了正常的案例延續)。
OnlyOnFaulted
選項適用於前一個Task
無法正確執行任務的情況。 一種方法是在每個延續任務中重新拋出異常,但那將是糟糕的設計。
如果要像普通對象一樣傳遞異常,則將其視為一個。 讓Task
返回異常並在Task.Result
中使用Task.Result
屬性。
我們現在在openstack.net SDK中使用的方法是CoreTaskExtensions.cs
的擴展方法。
方法有兩種形式:
Then
:continuation返回一個Task
,並自動調用Unwrap()
。 Select
:continuation返回一個對象,並且不會調用Unwrap()
。 此方法僅適用於輕量級延續,因為它始終指定TaskContinuationOptions.ExecuteSynchronously
。 這些方法具有以下好處:
AggregateException
包裝在異常中)。 supportsErrors=true
)。 Task
Continuations同步執行,並為您調用Unwrap()
。 以下對比顯示了我們如何將此更改應用於最初使用ContinueWith
和Unwrap
CloudAutoScaleProvider.cs :
https://github.com/openstacknetsdk/openstack.net/compare/3ae981e9...299b9f67#diff-3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.