![](/img/trans.png)
[英]C# - Does calling Task.Result wait until result is returned before returning
[英]What does accessing a Result on a Task before calling Wait actually do?
var task = Task.Run(() => DoSomeStuff()).Result;
引擎蓋下會發生什么?
我做了一個小測試:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
var r = Task.Run( () => {Thread.Sleep(5000); return 123; }).Result;
Console.WriteLine(r);
}
}
5 秒后打印“123”。 那么訪問Task
上的任何此類屬性是否可以作為調用Task.Wait()
的快捷方式,即這樣做是否安全?
以前我的代碼稱為Task.Delay(5000)
,它立即返回“123”。 我在我的問題中解決了這個問題,但把它留在這里作為評論和答案參考它。
你問了兩個問題。 首先,訪問Result
隱式導致同步Wait
? 是的。 但更重要的問題是:
這樣做安全嗎?
這樣做是不安全的。
很容易陷入這樣一種情況:您正在同步等待的任務在它完成到您剛剛進入 sleep的線程之前已安排在將來運行。 現在我們有一種情況,在休眠線程完成一些工作之前,線程不會喚醒,因為它處於休眠狀態,所以它永遠不會這樣做。
如果您已經知道任務已完成,那么同步等待結果是安全的。 如果不這樣做,那么同步等待是不安全的。
現在,您可能會說,假設我通過其他方式知道同步等待未完成的任務是安全的。 那么等待是否安全? 那么,對這個問題的前提,是的,但它仍然可能不聰明的等待。 請記住,異步的全部意義在於在高延遲的世界中有效地管理資源。 如果你正在同步等待一個異步任務完成,那么你就是在強迫一個 worker 休眠,直到另一個 worker 完成; 睡覺的工人可能正在工作! 異步的全部意義在於避免工人閑置的情況,所以不要強迫他們這樣做。
await
是異步等待。 這是一個等待,意思是“等待運行當前工作流的其余部分,直到此任務完成后,但在等待時找到一些事情要做”。 我們做了很多工作來將它添加到語言中,所以請使用它!
那么訪問
Task
上的任何此類屬性是否可以作為調用Task.Wait()
的快捷方式?
是的。
從文檔:
訪問 [
Result
] 屬性的 get 訪問器會阻塞調用線程,直到異步操作完成; 相當於調用了Wait方法。
但是,您的測試並沒有像您認為的那樣做。
Task.Delay(..)
返回一個在指定時間后完成的Task
。 它不會阻塞調用線程。
所以() => { Task.Delay(5000); return 123; }
() => { Task.Delay(5000); return 123; }
() => { Task.Delay(5000); return 123; }
簡單地創建一個新的Task
(其將在5秒內完成),然后引發它扔掉並立即返回123
。
您可以:
Task.Delay(5000).Wait()
(與Thread.Sleep(5000)
做同樣的事情Task.Delay(5000).Wait()
阻塞調用線程Task.Delay
返回的Task
完成: Task.Run(async () => { await Task.Delay(5000); return 123; })
測試不等待Task.Delay()
所以它立即返回。 它應該是 :
var r = Task.Run(async () => { await Task.Delay(5000); return 123; }).Result;
Result
的行為是明確定義的——如果任務還沒有完成,它就會阻塞直到它完成。 訪問其他任務屬性不會阻止
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.