如何让异步代码等到所有任务完成?

时间:2017-01-19 15:57:18

标签: c# asynchronous .net-4.5

当我运行下面的代码时,在"Press Enter to continue... "调用返回结果之前,会显示消息HttpClient.GetAsync()。实际的事件顺序:GetAsync()来电,&#34; Press Enter...&#34;消息出现,然后结果是逐个输出到控制台窗口。在显示&#34; GetAsync()&#34;&#34; Press Enter...&#34;之前,我如何等待所有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(); } } 来电完成消息?

{{1}}

4 个答案:

答案 0 :(得分:3)

由于DownloadPageAsync返回任务,您可以列出所有任务并等待所有任务:

Task.WhenAll(urls.Select(url => DownloadPageAsync(url)))

或简化:

Task.WhenAll(urls.Select(DownloadPageAsync))

答案 1 :(得分:1)

@ patrik-hofman答案很好(已投票)但是,请参阅我的评论

如果您希望顺序发生请求... 将await添加到DownloadPageAsync行。

您在async中使用了RunAsync,但没有await。因此,虽然它返回一个任务,但它不等待DownloadPageAsync调用完成。这意味着该方法只返回一个立即完成的“空”任务。所以你的.Wait()正在等待什么。

答案 2 :(得分:0)

我认为问题在于您没有等待DownloadPageAsync方法中的RunAsync()方法。如果您将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);
    }
}

答案 3 :(得分:-2)

您需要为每个所需的呼叫创建不同的任务,在您的示例中,您正在运行代码而不是等待呼叫。当你调用WhenAll时,它只是为所有人创建一个任务。假设您使用下面的代码,并在每个MakeYouCall方法中插入一个项目列表。该列表将是您需要锁定的共享资源。当创建WhenAll时,如果您不等待结果(调用Wait()),则可以部分填充集合。

spring-data mongo 

然后

var register1 = new Action(() => MakeYourCall1());
var register2 = new Action(() => MakeYourCall2());
var register3 = new Action(() => MakeYourCall3());

之后,您可以调用将返回任务的WhenAll,然后等待它。

var t1 = Task.Factory.StartNew(register1);
var t2 = Task.Factory.StartNew(register2);
var t3 = Task.Factory.StartNew(register3);