2013-04-22 60 views
4

以下是不是多餘的?正在等待的任務等於拋出異常的故障任務在ContinueWith

await blob.CopyToBlobAsync(newBlob). 
     ContinueWith((t) => { if (t.IsFaulted) throw t.Exception; }); 

好像沒有ContinueWith調用,異常會直接拋出?

什麼時候會使用continueWith而不是等待任務?

下面是一樣的嗎?

await myTask.ContinueWith(t => {'do something with the task t'}); 

await myTask; 
'do something with the task MyTask' 

回答

4

ContinueWith(t => { if (t.IsFaulted) throw t.Exception; })線已經不僅僅是await荷蘭國際集團直接CopyToBlobAsync任務不同的語義:

  • 它忽略取消的結果;即使CopyToBlobAsync返回的Task被取消,由ContinueWith返回的Task也會成功完成。這可能是有意的行爲。
  • 它忽略了成功的結果;從CopyToBlobAsync中刪除任何返回值。
  • 它通過直接拋出t.Exception包裝AggregateException中的任何例外。這幾乎是肯定的錯誤行爲。

所以它不是正是多餘的,是可能一個錯誤。

在某些情況下,您可以使用ContinueWith而不是await任務。在我的代碼中,如果延續很簡單,我通常只會這樣做,我不需要延續中的上下文,也不需要狀態機的開銷。對於大多數情況下,您應該更喜歡await可能結合ConfigureAwait(false)

你最後的例子不一樣;默認情況下,ContinueWith將在線程池中執行,默認情況下await將捕獲上下文並在該上下文中執行延續。另外,你必須非常小心你在繼續任務中的使用方式:通常你需要將異常和取消消息傳播給繼續任務,這並不像第一次出現那樣容易。

總之,我幾乎在每種情況下都推薦await。寫起來更容易,閱讀更容易,並且具有合理的默認行爲。

+0

我有一種情況,我在一個循環中創建和啓動任務,並使用信號限制併發運行任務的數量。我繼續關於這些任務,並檢查它們是否失敗,如果是這樣,則向一個ConcurrentBag添加一個ID,這樣我可以看到是否全部成功。我無法從我的continueWith委託中正確地得到正確的門的異常到我的out任務,即運行循環的任務。 (這聽起來很愚蠢,還是應該加上澄清的代碼)。 – 2013-04-22 19:47:40

+0

我建議您查看TPL數據流。這聽起來像是對你的情況有用。 – 2013-04-22 20:28:37

+0

ActionBlock對我的情況可能會很有趣。是否正確理解,我可以將其定義爲需要多次運行的代碼,只要有輸入就將輸入發佈給它。 – 2013-04-22 22:24:00