[英]How do I get async code to wait until all tasks are complete?
當我運行下面的代碼時,在從HttpClient.GetAsync()
調用返回結果之前,會出現消息"Press Enter to continue... "
。 實際的事件順序:進行GetAsync()
調用,出現“ Press Enter...
”消息,然后將結果一一輸出到控制台窗口。 在顯示“ Press Enter...
”消息之前,如何等待直到所有GetAsync()
調用完成?
class Program
{
static HttpClient client = new HttpClient();
static void Main(string[] args)
{
RunAsync().Wait();
Console.WriteLine("\n\n\n\nPress Enter to continue... ");
Console.ReadLine();
}
static async Task RunAsync()
{
List<string> urls = new List<string>()
{
"http://www.domain1.com",
"http://www.domain2.com",
"http://www.domain3.com",
"http://www.domain4.com"
};
foreach (var url in urls)
{
DownloadPageAsync(url);
}
}
static async Task<string> DownloadPageAsync(string url)
{
Console.WriteLine("Starting: " + url);
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
// do stuff here
}
Console.WriteLine("Done: " + url);
return response.Content.ToString();
}
}
由於DownloadPageAsync
返回任務,因此您可以列出所有任務並等待所有任務:
Task.WhenAll(urls.Select(url => DownloadPageAsync(url)))
或簡化:
Task.WhenAll(urls.Select(DownloadPageAsync))
@ patrik-hofman的答案是一個很好的答案(已投票通過),請參閱我的評論
如果您希望請求按順序發生,請...在DownloadPageAsync
行中添加await
。
您在RunAsync
使用了async
,但是沒有await
。 因此,盡管它返回一個Task,但它並不等待DownloadPageAsync
調用完成。 這意味着該方法僅返回立即完成的“空”任務。 因此,您的.Wait()
沒有任何等待。
我認為問題在於您沒有等待RunAsync()
方法中的DownloadPageAsync
方法。 如果將RunAsync()
方法更新為以下代碼,那么我相信它會按預期工作:
static async Task RunAsync()
{
List<string> urls = new List<string>()
{
"http://www.domain1.com",
"http://www.domain2.com",
"http://www.domain3.com",
"http://www.domain4.com"
};
foreach (var url in urls)
{
// added await here
await DownloadPageAsync(url);
}
}
您需要為每個所需的呼叫創建不同的任務,在您的示例中,您正在運行代碼而不等待呼叫。 當您調用WhenAll時,僅會為所有這些任務創建一個任務。 假設您使用下面的代碼,並且在每個MakeYouCall方法內部在列表中插入一個項目。 該列表將是您需要鎖定的共享資源。 當創建WhenAll時,如果您不等待結果(調用Wait()),則可以部分填充集合。
var register1 = new Action(() => MakeYourCall1());
var register2 = new Action(() => MakeYourCall2());
var register3 = new Action(() => MakeYourCall3());
然后
var t1 = Task.Factory.StartNew(register1);
var t2 = Task.Factory.StartNew(register2);
var t3 = Task.Factory.StartNew(register3);
之后,您可以調用WhenAll,它將返回一個Task,然后等待它。
Task.WhenAll(t1, t2, t3).Wait();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.