使用 WhenAll 和 ContinueWith 时任务结果的顺序是什么
本文关键字:结果 顺序 是什么 任务 WhenAll ContinueWith 使用 | 更新日期: 2023-09-27 18:32:58
只是想知道使用 WhenAll 和 ContinueWith 时任务结果的顺序是什么。这些结果是否与任务 ID 的顺序相同?
我在下面写了代码
public static async Task<string> PrintNumber(int number)
{
return await Task.Delay(number*1000).ContinueWith(_=>
{
Console.WriteLine(number);return "TaskId:"+Task.CurrentId+" Result:"+number;
});
}
public static void Main()
{
Task.WhenAll(new[]
{
PrintNumber(3),
PrintNumber(2),
PrintNumber(1),
}).ContinueWith((antecedent) =>
{
foreach(var a in antecedent.Result)
{
Console.WriteLine(a);
}
});
}
并在 linqpad 中运行几次以获得相同的结果
1
2
3
TaskId:15 Result:3
TaskId:14 Result:2
TaskId:13 Result:1
或
1
2
3
TaskId:18 Result:3
TaskId:17 Result:2
TaskId:16 Result:1
通过该特定调用,Task[]
的参数 - 顺序无法保证。
事实上,根据Task.WhenAll(Task[])
文件,根本没有提到秩序。但是,如果您使用Task.WhenAll(IEnumerable<Task<TResult>>)
重载,则其内容如下:
如果没有任何任务出错,并且没有取消任何任务,则生成的任务将以 RanToCompletion 状态结束。返回任务的结果将被设置为一个数组,其中包含所提供任务的所有结果,其顺序与提供顺序相同(例如,如果输入任务数组包含 t1、t2、t3,则输出任务的结果将返回一个 TResult[],其中 arr[0] == t1。结果,到达 arr1 == t2。结果,和 arr[2] == t3。结果)。
调用Task.WhenAll
(使用枚举数组或参数数组)时,结果的顺序与传递给该方法的任务的顺序匹配。
也就是说,这是真的:
var task1 = PrintNumber(3);
var task2 = PrintNumber(2);
var task3 = PrintNumber(1);
var taskResults = await Task.WhenAll(task1, task2, task3);
// taskResults[0] is the same as task1.Result
// taskResults[1] is the same as task2.Result
// taskResults[2] is the same as task3.Result
然而,ContinueWith
是一个完全不同的故事。 ContinueWith
附加一个延续,此延续将在任务完成后的某个时间运行。
在您的特定代码中,您不会将延续附加到传递给 Task.WhenAll
的任务。但是,如果您是,那么该延续可以在该任务完成后的任何时间运行。
附带说明一下,不要使用ContinueWith
(正如我在博客上解释的那样)。只需改用await
;生成的代码更正确、更清晰、更易于维护。