如何为大批量快速取消 Task.AwaitAll

How to fast cancel Task.AwaitAll for larger batches

假设我有这样一个片段:

public async Task WorkItem(WorkItem workItem, CancellationToken token) {
  Logger.Log("Starting...");
  token.ThrowIfCancellationRequested();
}

public async Task BatchProcessor(IList<WorkItem> workItems, CancellationToken token) {
  var tasks = workItems.Select(wi => WorkItem(wi, token)).ToList();
  await Task.WhenAll(tasks);
}

这很好 - 问题是代码应该在检索到取消令牌时快速取消(对于服务结构关闭场景) - 当你一个接一个地取消任务时,你实际上在点击之前进入了方法体异常抛出部分 - 当您有很多工作项时,这是一个问题。

我在想

var task = Task.Delay(Timeout.Infinite, token);
await Task.WhenAny(new List<Task> { task, Task.WhenAll(tasks) });

一旦收到取消令牌,它实际上会快速完成该方法,但不会解决关闭与新任务弹出的问题。

我想正确的解决方案是某种分区程序 - 任务有类似的东西吗?

根据@nvoigt 的建议,使用并行 Linq 的解决方案相当简单。修改后的查询如下所示:

var tasks = workItems.AsParallel().WithCancellation(token).Select(wi => WorkItem(wi, token));
await Task.WhenAll(tasks);

然后取消会更迅速。