只想知道使用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
答案 0 :(得分:4)
通过该特定调用,Task[]
的参数 - 订单不保证。
事实上,根据Task.WhenAll(Task[])
文件,没有提到任何顺序。但如果您使用Task.WhenAll(IEnumerable<Task<TResult>>)
重载,则会将其读为follows:
如果没有任何任务出现故障而且没有任何任务被取消,则生成的任务将以RanToCompletion状态结束。返回任务的结果将被设置为一个数组,其中包含所提供任务的所有结果,其顺序与提供的顺序相同(例如,如果输入任务数组包含t1,t2,t3,输出任务的结果将返回一个TResult [],其中arr [0] == t1.Result,arr1 == t2.Result,和arr [2] == t3.Result)。
答案 1 :(得分:2)
当你调用Task.WhenAll
(带有enumerable或params数组)时,结果的顺序与传递给该方法的任务的顺序相匹配。
也就是说,这是真的:
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
的任务中附加延续。但是,如果你是,那么在该任务完成后,该延续可以随时运行。
旁注,don't use ContinueWith
(正如我在博客中解释的那样)。只需使用await
代替;生成的代码更正确,更清晰,更易于维护。