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

使用AsParallel.ForAll搭配异步代码未等待完成,是否为预期行为?

关于AsParallel().ForAll()在异步场景下不阻塞的问题

首先明确:AsParallel().ForAll()本身是同步阻塞方法,在传入同步委托时,它会等待所有并行任务执行完成后才会继续后续代码——这也是你同步场景下运行正常的原因。

但你改成异步后出现"Done!"先输出的情况,核心问题出在你传给ForAll的是异步lambda(async () => { ... }):

  • ForAll接受的是Action<T>类型的委托,而异步lambda会被隐式转换为async void方法(因为Action没有返回值)。
  • async void是异步编程中的特殊情况:调用方无法等待它的执行完成,调用后会立即返回。所以ForAll会误以为每个委托都已经执行完毕(实际只是启动了异步操作),直接继续执行后续的"Done!"代码,而异步任务还在后台运行。

这不是你的操作错误,而是对异步委托与PLINQ结合的特性不熟悉,这种行为是async void的预期表现。

正确的异步并行处理方式

如果需要在并行场景中处理异步操作,不要用AsParallel().ForAll(),推荐以下两种方式:

方式1:使用Parallel.ForEachAsync(.NET 6+支持)

这是官方推荐的异步并行遍历方法,能正确等待所有异步任务完成:

await Parallel.ForEachAsync(Enumerable.Range(1, 5), async (num, ct) =>
{
    await Task.Delay(100, ct);
    Console.WriteLine(num);
});
Console.WriteLine("Done!");

方式2:PLINQ结合Task.WhenAll

通过PLINQ生成异步任务集合,再用Task.WhenAll等待所有任务完成:

var asyncTasks = Enumerable.Range(1, 5).AsParallel().Select(async num =>
{
    await Task.Delay(100);
    Console.WriteLine(num);
});
await Task.WhenAll(asyncTasks);
Console.WriteLine("Done!");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:42:37