同时等待具有自主延续多个异步调用 [英] Concurrently awaiting multiple asynchronous calls with independent continuations
问题描述
有几种情况下,我需要调用多个异步调用(来自同一事件处理程序),可以独立进行相互的,都有自己的延续每一个更新的用户界面。
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屋!