我有以下代码:
List<Task<bool>> tasks = tasksQuery.ToList();
while (tasks.Any())
{
Task<bool> completedTask = await Task.WhenAny(tasks);
if (await completedTask)
return true;
tasks.Remove(completedTask);
}
它并行启动任务。当第一个完成的任务返回true时,方法返回true。
所有已启动且可能仍在后台运行的剩余任务会发生什么? 这是执行异步,并行代码的正确方法,应该在第一个条件发生后返回,还是最好逐个启动它们并等待?
由于
答案 0 :(得分:13)
顺便说一下,我只是按Concurrency in C# CookBook阅读Stephen Cleary,我猜这里可以参考本书的某些部分。
从食谱2.5 - 讨论,我们有
第一个任务完成后,请考虑是否取消剩余的任务。如果其他任务没有被取消但也从未等待过,那么它们就会被放弃。 废弃的任务将完成,其结果将被忽略。这些被遗弃的任务的任何例外也将被忽略。
Task.WhenAny的另一个反模式是在完成任务时处理任务。 首先,保持任务列表并在完成后从列表中删除每个任务似乎是一种合理的方法。这种方法的问题在于,当存在O(N)算法时,它在O(N ^ 2)时间内执行。
除此之外,我认为WhenAny
肯定是正确的方法,只需考虑遵循Leonid方法将相同的CancellationToken
传递给每个任务,并在第一个任务返回后取消它们。而且,即使这些操作的成本实际上对系统征税,也是如此。