2012-08-23 114 views
37

我試圖圍繞TPL,C#5中的新async/await功能以及TaskCompletionSource的奧祕包圍我的頭。TaskCompletionSource:何時使用SetResult()和TrySetResult()等

有一件事情是我不明白是什麼時候使用SetResultSetException,並SetCancelTrySetResultTrySetExceptionTrySetCancel

這是MSDN不得不說:

該操作將返回false,如果該任務已經在三個最終狀態 之一:RanToCompletion,斷陷,或取消。

如果基礎任務的 已被丟棄,此方法也會返回false。

好吧,我明白了,但它並沒有真正提供任何指導什麼時候或爲什麼要使用一個。

那麼,這是怎麼回事?

回答

46

嫌疑的一點是,如果只有一件事情將要設置的結果,只需要調用SetResult等,如果你最終調用SetResult兩次,指示的錯誤。 (同樣,如果TaskCompletionSource已被處置)。

如果您有幾個線程可能都試圖同時設置結果(例如,它指示幾個並行Web服務調用中的第一個結果)然後使用TrySetResult,因爲多線程「嘗試」設置結果是完全合理的,不知道另一個線程是否已經設置了它。

我還沒有看到任何官方指導,但這是有道理的。

+8

即真的,您需要調用'TrySetResult'的唯一原因是您不止一次設置結果。 'SetResult'「完成」相關的'Task',所以在任務完成後再次調用'SetResult'會嘗試設置'Task '的結果。 ('SetResult'阻塞,直到'Task'完成 - 就象'TrySetResult'一樣)如果你只調用一次'SetResult',那麼你永遠不需要'TrySetResult'。 FWIW。 'SetResult'鏈到'TrySetResult' ... –

+0

謝謝你們,你們很有道理! – HolySamosa

+0

還要注意,SetResult返回'void',而TrySetResult返回'bool',所以如果你想根據任務狀態有條件地做一些事情,那麼'TrySetResult'同時檢查和設置(原子?)。 – chakrit

相關問題