如何判断Parallel.ForEach执行完毕以执行后续指令?
问题解决:等待异步并行操作完成后再记录日志
你的核心问题是**Parallel.ForEach不支持异步委托**,传入的async Entry => ...属于async void类型的方法,Parallel.ForEach只会启动这些异步任务,但不会等待它们执行完毕,所以日志会直接跳过循环提前输出。哪怕用Task.Run包裹,也只是等Parallel.ForEach的循环启动完所有任务,不会等异步操作结束。
正确解决方案
方案1:使用Task.WhenAll(兼容所有.NET版本)
把每个元素的异步操作转换成Task集合,再用Task.WhenAll等待所有任务完成:
// 生成所有异步任务 var tasks = grpfiles.Select(entry => Process(entry.ToList())); // 等待所有任务执行完毕 await Task.WhenAll(tasks); // 此时所有异步操作都已完成,再记录日志 _logger.LogInformation($"End function at: {DateTime.Now}");
方案2:使用Parallel.ForEachAsync(.NET 6及以上版本推荐)
这是官方为异步并行迭代专门设计的API,能正确跟踪并等待所有异步操作完成:
await Parallel.ForEachAsync(grpfiles, async (entry, cancellationToken) => { await Process(entry.ToList()); }); _logger.LogInformation($"End function at: {DateTime.Now}");
原写法失效原因
Parallel.ForEach是为同步代码设计的,它不识别异步lambda的返回值(Task),会把异步lambda当作async void方法处理。这种方法的异步任务无法被跟踪,Parallel.ForEach执行到lambda里的第一个await时,就会直接开始下一个迭代,不会等待整个异步方法完成。- 用
Task.Run包裹的写法,只是让主线程等待Parallel.ForEach的循环体执行完毕(也就是所有async void任务都启动了),但这些任务的异步逻辑还在后台运行,所以日志还是会提前输出。
内容的提问来源于stack exchange,提问作者lizarazou
相关产品推荐
相关产品推荐

