【问题标题】:How to fast cancel Task.AwaitAll for larger batches如何快速取消大批量的 Task.AwaitAll
【发布时间】:2018-07-17 05:36:09
【问题描述】:

假设我有一个像这样的 sn-p:

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) });

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

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

【问题讨论】:

  • 每当我看到要并行处理的事情的列表时,我都会想到 PLinq 的AsParallel()。你试过吗?它可能比滚动你自己的版本做得更好。你可以传递一个 CancellationToken。
  • @nvoigt - 是否愿意将其表述为答案?

标签: c# task cancellation


【解决方案1】:

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

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

然后取消更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 2011-04-21
    相关资源
    最近更新 更多