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

如何在C#中获取List<T>.AsParallel()的执行结果?

问题分析

你这段代码的核心问题有两个:

  1. AsParallel().ForAll不支持异步委托——你传入的async lambda会被当作async void执行,属于“fire-and-forget”(只管触发不管结果)的异步操作,不仅没法收集返回值,程序还可能在任务没跑完就继续往下执行。
  2. PLINQ(即AsParallel相关API)是针对CPU密集型任务设计的,而你的Test方法是IO密集型(用Task.Delay模拟IO等待),用它反而会浪费资源。
最优解决方案:IO密集型场景用Task.WhenAll

对于IO密集型的异步任务,直接用Task.WhenAll配合LINQ生成任务列表是最高效的,完全不需要PLINQ:

var x = new[] { 0, 1 };
var y = new[] { 2, 3 };
// 先生成所有要执行的异步任务
var tasks = x.Zip(y, (xVal, yVal) => Test(xVal, yVal)).ToList();
// 等待所有任务完成,一次性获取所有结果
var results = await Task.WhenAll(tasks);
// 此时results就是你要的[0,1]

这个方案的优势:

  • 天然适配异步逻辑,能正确等待所有任务结束,完美收集返回值。
  • IO密集型任务不需要占用大量线程,线程池会自动调度,资源利用率比PLINQ高得多。
CPU密集型场景的PLINQ正确用法

如果后续你的Test改成CPU密集型操作(比如复杂计算),再用PLINQ才合理,而且要改用Select来收集结果,而非ForAll:

// 假设Test变成同步CPU密集方法:static int Test(int x, int y) { /* 耗时计算逻辑 */ }
var zipped = x.Zip(y, (xVal, yVal) => new { xVal, yVal }).ToList();
var results = zipped.AsParallel()
                    .Select(pair => Test(pair.xVal, pair.yVal))
                    .ToList();

// 如果还是异步但CPU密集(比如内部用Task.Run封装计算),可以这样写:
var results = zipped.AsParallel()
                    .Select(pair => Test(pair.xVal, pair.yVal).Result)
                    .ToList();

你还可以用WithDegreeOfParallelism手动指定并行度,比如.AsParallel().WithDegreeOfParallelism(4),控制同时运行的任务数量。

原代码失效的本质原因

ForAll的参数是Action<T>,当你传入async lambda时,它会被解析成async void方法——这种方法在异步编程里专门用于事件处理,它不会返回Task,所以你既没法等待它完成,也拿不到返回值,甚至任务抛出异常都没法主动捕获(除非加全局异常处理),完全不适合需要收集结果的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:55:13