调用Task.WhenAll()后获取结果



Task.WhenAll(params System.Threading.Tasks.Task[] tasks)返回Task,但是调用此方法后获取任务结果的正确方法是什么?等待该任务后,可以通过再次等待从原始任务获得结果,这应该是好的,因为任务已经完成。也可以使用任务来获得结果。结果属性,通常被认为是不好的做法

Task<TResult1> task1= ...
Task<TResult2> task2= ...
Task<TResult3> task3= ...
await Task.WhenAll(task1, task2, task3)
var a = task1.Result; // returns TResult1
var b = await task1; // also returns TResult1

我应该选择哪一个,为什么?

如果您真的只有IEnumerable<Task<TResult>>,并且任务将被创建为on-the-fly(例如由于.Select()),您将执行两次任务。

因此,请确保您要么给Task.WhenAll()一个已经物化的集合,要么从该方法的返回值中获取结果:

var someTasks = Enumerable.Range(1, 10).Select(i => { Task.Delay(i * 100); return i; });
// Bad style, cause someTasks is an IEnumerable created on-the-fly
await Task.WhenAll(someTasks);
foreach(var task in someTasks)
{
var taskResult = await task;
Console.WriteLine(taskResult);
}
// Okay style, cause tasks are materialized before waiting, but easy to misuse wrong variable name.
var myTasks = someTasks.ToList();
await Task.WhenAll(myTasks);
foreach(var task in myTasks)
{
Console.WriteLine(task.Result);
}
// Best style
var results = await Task.WhenAll(someTasks);
foreach(var result in results)
{
Console.WriteLine(result);
}

更新读一读你的问题:

然而,我找不到任何重载,只能返回Task。

如果给Task.WhenAll()方法的任务集合不共享一个通用的Task<T>类型,就会发生这种情况。这可能发生,例如,如果你想并行运行两个任务,但都返回不同的值。在这种情况下,您必须将任务具体化,然后单独检查结果:

public static class Program
{
public static async Task Main(string[] args)
{
var taskOne = ReturnTwo();
var taskTwo = ReturnPi();
await Task.WhenAll(taskOne, taskTwo);
Console.WriteLine(taskOne.Result);
Console.WriteLine(taskTwo.Result);
Console.ReadKey();
}
private static async Task<int> ReturnTwo()
{
await Task.Delay(500);
return 2;
}
private static async Task<double> ReturnPi()
{
await Task.Delay(500);
return Math.PI;
}
}

返回Task<TResult[]>- MS Docs的重载

的例子:

static async Task Test()
{
List<Task<string>> tasks = new List<Task<string>>();
for (int i = 0; i < 5; i++)
{
var currentTask = GetStringAsync();
tasks.Add(currentTask);
}
string[] result = await Task.WhenAll(tasks);
}
static async Task<string> GetStringAsync()
{
await Task.Delay(1000);
return "Result string";
}

最新更新