天天看點

Task.Result跟 Task.GetAwaiter.GetResult()相同嗎?怎麼選?

前幾天在用線程池執行一些任務時運到一種情形,就是回調方法中使用到了異步方法,但是回調方法貌似不支援

async await

的寫法。這時候我應該如何處理呢?是使用

Task.Result

來擷取傳回結果,還是使用

GetAwaiter.GetResult()

呢?本文就來探讨下吧。

作者:依樂祝

原文位址:https://www.cnblogs.com/yilezhu/p/13168337.html

這裡先上我這種場景的僞代碼:

ThreadPool.QueueUserWorkItem(ExcuteScanProcess, node);
           

ExcuteScanProcess

這個回調方法中

private void ExcuteScanProcess(object state)
{
    ……其他處理……
    repository.UpdateAsync(node).ConfigureAwait(false).GetAwaiter().GetResult();
    ……其他處理……
}
           

如上圖所示

repository.UpdateAsync(node)

屬于一部方法,這時候我想要等待它異步執行完成之後再執行後續的邏輯。這時候我有兩種選擇,是直接

repository.UpdateAsync(node).ConfigureAwait(false).GetAwaiter().GetResult();
           

好呢,還是

repository.UpdateAsync(node).ConfigureAwait(false).Result;
           

好呢?

為此我查找了相關的資料,對它倆的差別做一個簡單的總結:

其實這兩個使用方式是差不多的。不過,還是有一點小小的差別的:如果任務失敗,

Task.GetAwaiter().GetResult()

會直接抛出異常,而

Task.Result

則會把異常包裝在

AggregateException

中。從這個角度說

Task.GetAwaiter().GetResult()

要優于

Task.Result

。畢竟它少了異常的包裝操作,即直接抛出異常,而不是把異常包裝在

AggregateException

中。

下面的引言解釋了為什麼

Task.Result

不僅僅包含

Task.GetAwaiter().GetResult()

(由于“非常高的相容性”)的異常傳播行為。

如前所述,我們有一個非常高的相容性标準,是以我們避免了改動。是以,

Task.Wait

保留了始終包裝的原始行為。但是,您可能會發現自己處在某些進階情況下,這些情況下您想要的行為類似于所采用的同步阻塞

Task.Wait

,但是您希望将原始異常展開而不是傳播,而不是将其封裝在

AggregateException

中。為此,您可以直接定位任務的等待者。當您編寫“

await task;

”時,編譯器

Task.GetAwaiter()

會将其轉換為方法的用法,這将傳回具有

GetResult()

方法的執行個體。當用于有故障的任務時,

GetResult()

将傳播原始異常(這是“

await task;

” 如何獲得其行為)。是以,您可以使用“

task.GetAwaiter().GetResult()

如果您想直接調用此傳播邏輯。

https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

GetResult

”實際上表示“檢查任務是否有錯誤”

通常,我會盡力避免對異步任務進行同步阻塞。但是,在少數情況下,我确實違反了該準則。在那些罕見的情況下,我的首選方法是

GetAwaiter().GetResult()

因為它保留任務異常,而不是将它們包裝在中

AggregateException

總結

通過上述内容的闡述,是以在那些必須對異步任務進行同步阻塞的場景中,我選擇使用

GetAwaiter().GetResult()

作者:依樂祝(祝雷)

出處:https://www.cnblogs.com/yilezhu

聯系:[email protected] .NET Core實戰項目交流群:637326624 微信:jkingzhu

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。如有問題或建議,請多多賜教,非常感謝。

Task.Result跟 Task.GetAwaiter.GetResult()相同嗎?怎麼選?

繼續閱讀