同时等待具有自主延续多个异步调用 [英] Concurrently awaiting multiple asynchronous calls with independent continuations

查看:106
本文介绍了同时等待具有自主延续多个异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有几种情况下,我需要调用多个异步调用(来自同一事件处理程序),可以独立进行相互的,都有自己的延续每一个更新的用户界面。

There are several scenarios where I need to invoke multiple asynchronous calls (from the same event handler) that can proceed independently of each other, with each one having its own continuation for updating the UI.

以下幼稚执行导致三个异步操作可以顺序执行:

The following naive implementation causes the three asynchronous operations to be executed sequentially:

private async void button_Click(object sender, RoutedEventArgs e)
{
    nameTextBox.Text = await GetNameAsync();
    cityTextBox.Text = await GetCityAsync();
    rankTextBox.Text = await GetRankAsync();
}

这里有一个 MSDN例如这表明分离的任务创建从各自的await语句,使他们能够并行运行:

There's an MSDN example that suggests separating the creation of the tasks from their respective await statements, allowing them to be run in parallel:

private async void button_Click(object sender, RoutedEventArgs e)
{
    var nameTask = GetNameAsync();
    var cityTask = GetCityAsync();
    var rankTask = GetRankAsync();

    nameTextBox.Text = await nameTask;
    cityTextBox.Text = await cityTask;
    rankTextBox.Text = await rankTask;
}

但是,这种方法的局限性在于延续任务仍注册顺序,这意味着的 N 之前延续其所有$ P $不能执行pceding的 N 的-1延续已经完成,即使它的任务可能是第一个完成。

However, the limitation of this approach is that the task continuations are still registered sequentially, meaning that the nth continuation can't execute before all its preceding n−1 continuations have completed, even though its task may be the first to complete.

什么是用于获取异步任务并行运行的最佳模式,但每次都延续只要其各自的任务完成运行?

What is the best pattern for getting the asynchronous tasks to run in parallel, but have each continuation run as soon as its respective task completes?

修改:大部分的答案建议等候的 Task.WhenAll ,象下面这样:

Edit: Most of the answers suggest awaiting on Task.WhenAll, like below:

private async void button_Click(object sender, RoutedEventArgs e)
{
    var nameTask = GetNameAsync(); 
    var cityTask = GetCityAsync(); 
    var rankTask = GetRankAsync(); 

    await Task.WhenAll(nameTask, cityTask, rankTask);

    nameTextBox.Text = nameTask.Result;
    cityTextBox.Text = cityTask.Result;
    rankTextBox.Text = rankTask.Result;
}

不过,这不符合我的要求,因为我需要每一个延续,只要其各自的任务完成执行。例如,假设 GetNameAsync 需要5秒, GetCityAsync 需要2秒, GetRankAsync 需要8秒。上面的实施将导致所有三个文本框只能后8秒被更新,即使结果为 nameTextBox cityTextBox 较早前多大名气。

However, this does not meet my requirement, as I need each continuation to execute as soon as its respective task completes. For example, suppose that GetNameAsync takes 5 s, GetCityAsync takes 2 s, and GetRankAsync takes 8 s. The implementation above would cause all three textboxes to only be updated after 8 s, even though the results for nameTextBox and cityTextBox were known much earlier.

推荐答案

一个简单的替代方法是:

A simpler alternative would be:

private async void button_Click(object sender, RoutedEventArgs e)
{
    var results = await Task.WhenAll(
        GetNameAsync(),
        GetCityAsync(),
        GetRankAsync()
    );

    nameTextBox.Text = results[0];
    nameCityBox.Text = results[1];
    nameRankBox.Text = results[2];
}

没有关闭,没有多余的状态机。

No closures, no extra state machines.

这篇关于同时等待具有自主延续多个异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆