2016-03-10 29 views
1

我有一個Task<T> t1。我想在t1完成後運行另一個Task t2。我選擇使用t1.ContinueWith方法。ContinueWith爲什麼通過任務作爲參數

void ThenFrob(Task<Frobber> t1) { 
    t1.ContinueWith(frobber => frobber.Frob()) 
} 

除此之外,我不能這樣做,因爲Task<T> Action參數傳遞的Task<T>,而不是T本身。相反,我必須將傳遞給我的動作的參數的結果與它進行交互。

void ThenFrob(Task<Frobber> t1) { 
    t1.ContinueWith(frobberTask => { 
     var frobber = frobberTask.Result; 
     frobber.frob(); 
    }); 
} 

如果ContinueWith的點到另一個動作加入連鎖,爲什麼不語言設計者簡單地通過了前一個任務的結果呢?或者,如果非通用任務期望進行無參數操作?

+1

以前的任務結果是什麼,如果任務拋出異常? – PetSerAl

+0

根據非並行開發或Promises思考,我期望有一個不同的方法簽名來處理異常。繼續暗示我以前的任務已經完成,沒有錯誤。 – psaxton

+1

順便說一句,我認爲使用'ContinueWith(async t => {var result = await t ...})'而不是'.Result'是一種更好的做法,即使是有人會複製粘貼動作的最小風險到'.Result'可能會阻塞該線程的外部代碼中。 –

回答

2

ContinueWith在任務進入task.IsCompleted == true狀態時運行委託。不是當它進入task.IsCompleted == true && task.IsFaulted == false && task.IsCanceled == false狀態時,拋出異常的任務或取消的任務都會「完成」,但不會產生結果。

有重載,你可以在TaskContinuationOptionsTaskContinuationOptions.OnlyOnRanToCompletion通過讓行爲像你所描述的,但它會更復雜,有Action<T>重載只是一個枚舉選項,以便他們只是使用的Action<Task<T>>一般性過,所以你如果您在做OnlyOnRanToCompletion或者您在做OnlyOnFaulted,可以使用相同的方法。

而且還有一個完成任務的Task對象的有用信息,如果您使用的是AsyncState屬性通過元數據,如果完成任務並沒有轉嫁到ContinueWith你會不會有一種方式來獲得這些數據除非你使用了lambda表達式的變量捕獲。