[英]Async/Await single thread/some threads
我需要一個關於正確使用await的規則。 在.net core c#7.2中運行此代碼:
static class Program
{
static async Task<string> GetTaskAsync(int timeout)
{
Console.WriteLine("Task Thread: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(timeout);
return timeout.ToString();
}
static async Task Main()
{
Console.WriteLine("Main Thread: " + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Should be greater than 5000");
await Watch(NotParallel);
Console.WriteLine("Should be less than 5000");
await Watch(Parallel);
}
public static async Task Parallel()
{
var res1 = GetTaskAsync(2000);
var res2 = GetTaskAsync(3000);
Console.WriteLine("result: " + await res1 + await res2);
}
public static async Task NotParallel()
{
var res1 = await GetTaskAsync(2000);
var res2 = await GetTaskAsync(3000);
Console.WriteLine("result: " + res1 + res2);
}
private static async Task Watch(Func<Task> func) {
var sw = new Stopwatch();
sw.Start();
await func?.Invoke();
sw.Stop();
Console.WriteLine("Elapsed: " + sw.ElapsedMilliseconds);
Console.WriteLine("---------------");
}
}
你們都可以看到兩種方法的行為是不同的。 在實踐中很容易出錯。 所以我需要一個“拇指規則”。
真人的更新請運行代碼。 並解釋為什么Parallel()比NonParallel()運行得更快。
在沒有await
情況下調用GetTaskAsync
,你實際上得到一個Task,其中包含要執行的方法(即GetTaskAsync
)。但是當調用await GetTaskAsync
,執行將暫停,直到方法執行await GetTaskAsync
,然后你得到結果。
讓我更清楚一點:
var task = GetTaskAsync(2000);
這里,task的類型為Task<string>
。
var result = await GetTaskAsync(2000);
這里的結果是string
類型。
因此,要解決您的第一次詢問:何時等待您的任務實際上取決於您的執行流程。
現在,至於為什么Parallel()
更快,我建議你閱讀這篇文章 (一切都很有趣,但對於你的具體例子,你可以跳轉到Tasks返回“熱門” )。
現在讓我們分解一下:
await
關鍵字用於暫停代碼,直到任務完成,但實際上並未啟動它。
在您的示例中, NotParallel()
將花費更長時間,因為您的任務依次執行,一個接一個地執行。 正如文章所解釋的:
這是由於正在等待內聯任務。
Parallel()
然而......
這些任務現在並行運行。 這是因為所有[任務]在隨后等待所有[任務]之前開始,因為它們返回熱點。
我建議您閱讀以下內容: 基於任務的異步模式(TAP)
此處的“ 任務狀態”部分非常感興趣,可以了解冷熱任務的概念:
由公共任務構造函數創建的任務稱為冷任務,因為它們以非調度的創建狀態開始其生命周期,並且僅在這些實例上調用Start時進行調度。
所有其他任務在熱狀態下開始其生命周期,這意味着它們所代表的異步操作已經啟動
我邀請您詳細閱讀有關async/await
和Tasks
。 除了上面提供的資源之外,還有一些資源:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.