Task.WhenAny - 剩余的正在运行的任务会发生什么?

Ale*_*hke 24 c# task-parallel-library async-await

我有以下代码:

List<Task<bool>> tasks = tasksQuery.ToList();
while (tasks.Any())
{
    Task<bool> completedTask = await Task.WhenAny(tasks);
    if (await completedTask)
        return true;

    tasks.Remove(completedTask);
}
Run Code Online (Sandbox Code Playgroud)

它并行启动任务.当第一个完成的任务返回true时,方法返回true.

我的问题是:

所有剩余的任务已经启动并且可能仍然在后台运行会发生什么? 这是执行异步,并行和在第一个条件发生后应该返回的代码的正确方法,还是最好逐个启动它们并等待单独进行?

谢谢

hel*_*ker 15

顺便说一句,我只是读并发在C#食谱,由斯蒂芬·克利里,我可以参照这里的书的某些部分,我猜.

食谱2.5 - 讨论,我们有

第一个任务完成后,请考虑是否取消剩余的任务.如果其他任务没有被取消但也从未等待过,那么它们就会被放弃.被遗弃的任务将完成,其结果将被忽略.这些遗弃任务的任何例外也将被忽略.

Task.WhenAny的另一个反模式是在完成任务时处理任务.首先,保持任务列表并在完成时从列表中删除每个任务似乎是一种合理的方法.这种方法的问题在于,当存在O(N)算法时,它在O(N ^ 2)时间内执行.

除此之外,我认为WhenAny肯定是正确的方法,只需考虑遵循Leonid方法将相同的方法传递CancellationToken给每个任务,并在第一个任务返回后取消它们.即便如此,只有在这些操作的成本实际上对系统征税的情况下.

  • 以下是对 O(n^2) 内容的更多讨论:https://devblogs.microsoft.com/pfxteam/processing-tasks-as-they-complete/ (3认同)
  • 尼斯.请注意,您很可能会对所有任务使用_single_ CancellationToken. (2认同)
  • 什么是O(N)方法? (2认同)
  • 这不是 O(N^2) _time_ ,而是 O(N^2) 复杂性/开销,因为每次调用 .WhenAny() 都会安排剩余任务的完成(或者至少检查是否必须安排完成)。 (2认同)