[英]async & await - How to wait until all Tasks are done?
好。 我制作了一個簡單的控制台應用程序,以弄清楚如何完成所有這些工作。 一旦基本輪廓開始工作,然后將其應用於實際應用程序。
這個想法是,我們要執行很多數據庫調用,這將花費很長時間。 我們不想(或不必)等待一個數據庫調用完成之后再進行下一個。 它們可以同時運行。
但是,在進行所有調用之前,我們需要執行“啟動”任務。 當所有調用完成后,我們需要執行“完成”任務。
這是我現在的位置:
static void Main(string[] args)
{
Console.WriteLine("starting");
PrintAsync().Wait();
Console.WriteLine("ending"); // Must not fire until all tasks are finished
Console.Read();
}
// Missing an "await", I know. But what do I await for?
static async Task PrintAsync()
{
Task.Run(() => PrintOne());
Task.Run(() => PrintTwo());
}
static void PrintOne()
{
Console.WriteLine("one - start");
Thread.Sleep(3000);
Console.WriteLine("one - finish");
}
static void PrintTwo()
{
Console.WriteLine("two - start");
Thread.Sleep(3000);
Console.WriteLine("two - finish");
}
但是,無論我嘗試什么,《 Ending
總是打印得太早了:
starting
ending
one - start
two - start
one - finish
two - finish
IS的正確工作是在完成PrintTwo()
之前啟動PrintOne()
。 但是,在執行其他操作之前,如何正確等待PrintAsync()
完成?
您需要等待內部任務的結束:
static async Task PrintAsync()
{
await Task.WhenAll(Task.Run(() => PrintOne()), Task.Run(() => PrintTwo()));
}
說明: async Task
表示一個等待的方法。 在此方法內,您還可以await
任務。 如果您不這樣做,那么它將簡單地讓任務松散,這些任務將自行運行。 Task.Run
返回可以等待的Task
。 如果你想兩個任務並行運行,你可以從retur值使用的任務,並在awaitable方法使用它們Task.WhenAll
編輯:實際上,Visual Studio會用綠色彎曲線標記此代碼。 當將鼠標懸停在上面時,您會得到警告:
這應該可以解釋為什么在任務完成之前打印"ending"
編輯2:
如果您有要迭代的參數集合並調用異步方法以傳遞參數,則也可以在第一行中使用select語句來做到這一點:
static async Task DatabaseCallsAsync()
{
// List of input parameters
List<int> inputParameters = new List<int> {1,2,3,4,5};
await Task.WhenAll(inputParameters.Select(x => DatabaseCallAsync($"Task {x}")));
}
static async Task DatabaseCallAsync(string taskName)
{
Console.WriteLine($"{taskName}: start");
await Task.Delay(3000);
Console.WriteLine($"{taskName}: finish");
}
最后一部分類似於上一個答案
在這里操作。 我將Mong Zhu的答案標記為正確,因為它可以將我引向解決方案。 但我也想在這里分享最終結果,包括juharr的評論中的出色反饋。 這是我想出的:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting");
DatabaseCallsAsync().Wait();
Console.WriteLine("ending"); // Must not fire until all database calls are complete.
Console.Read();
}
static async Task DatabaseCallsAsync()
{
// This is one way to do it...
var tasks = new List<Task>();
for (int i = 0; i < 3; i++)
{
tasks.Add(DatabaseCallAsync($"Task {i}"));
}
await Task.WhenAll(tasks.ToArray());
// This is another. Same result...
List<int> inputParameters = new List<int> { 1, 2, 3, 4, 5 };
await Task.WhenAll(inputParameters.Select(x => DatabaseCallAsync($"Task {x}")));
}
static async Task DatabaseCallAsync(string taskName)
{
Console.WriteLine($"{taskName}: start");
await Task.Delay(3000);
Console.WriteLine($"{taskName}: finish");
}
}
結果如下:
starting
Task 0: start
Task 1: start
Task 2: start
Task 2: finish
Task 0: finish
Task 1: finish
ending
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.