簡體   English   中英

在連續鏈中傳播異常的正確方法是什么?

[英]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拋出AggregateExceptionTask.GetAwaiter().GetResult() - 否則等效 - 拋出基礎異常。)

要重申,這其實不是一個簡單的問題,你可能會感興趣的埃里克利珀的異常處理在C#5異步代碼的文章在這里這里

如果您不希望在發生異常(即日志記錄)時特別執行任何操作,並且只希望傳播異常,則只需在拋出異常時(或在取消時)運行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

這些方法具有以下好處:

  1. 當前因出現故障或取消時,避免調用延續方法。
  2. 相反,前提的結果成為鏈式操作的結果(准確保留異常信息,而不將多個AggregateException包裝在異常中)。
  3. 允許調用者編寫支持故障前提的延續方法,在這種情況下,僅取消前面的任務繞過延續(為擴展方法指定supportsErrors=true )。
  4. 返回Task Continuations同步執行,並為您調用Unwrap()

以下對比顯示了我們如何將此更改應用於最初使用ContinueWithUnwrap CloudAutoScaleProvider.cs
https://github.com/openstacknetsdk/openstack.net/compare/3ae981e9...299b9f67#diff-3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM