You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Parallel.ForEachAsync中CancellationTokenSource的正确用法咨询

这段代码中CancellationTokenSource的使用存在问题

核心问题点

  • 未关联外部传入的cancellationToken:外部调用方发起取消时,内部并行循环不会响应,不符合异步操作的取消规范。
  • 未将自定义CancellationTokenSource的Token传入Parallel.ForEachAsync:调用cancellationTokenSource.Cancel()后,并行循环不会停止调度新任务,已启动的任务也无法感知取消信号。
  • 未释放CancellationTokenSource资源:未用using包裹,存在资源泄漏风险。
  • 调用_service.GetObject时未传递取消Token:即使触发取消,正在执行的异步操作也无法被中断。

修正后的代码

public async Task<Result> Handle(MyQuery request, CancellationToken cancellationToken)
{
    // 关联外部取消信号,自动释放资源
    using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

    try
    {
        await Parallel.ForEachAsync(myList, cts.Token, async (objectId, token) =>
        {
            // 将取消Token传入服务方法,支持中途中断异步操作
            var result = await _service.GetObject(objectId, token);

            if (result.Any())
            {
                cts.Cancel();
                // 抛出取消异常,让Parallel.ForEachAsync快速终止所有任务
                token.ThrowIfCancellationRequested();
            }
        });
    }
    catch (OperationCanceledException)
    {
        return Result.Fail("Error message.");
    }

    return Result.Ok();
}

修正说明

  1. 用using包裹CancellationTokenSource,确保资源自动释放;通过CreateLinkedTokenSource关联外部取消信号,兼顾外部调用方和内部逻辑的取消需求。
  2. 将cts.Token传入Parallel.ForEachAsync,触发取消后,循环会停止调度新任务,已启动的任务也能通过Token感知取消。
  3. 调用_service.GetObject时传递取消Token,让异步操作可以在取消时被中断,避免无效等待。
  4. 触发取消后抛出OperationCanceledException,让Parallel.ForEachAsync快速终止所有任务,而非等待已启动任务全部完成。

内容的提问来源于stack exchange,提问作者user7849697

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:07:08