Parallel.ForEachAsync 是 .NET 6 引入的一个强大 API,它确实会实现并行处理,但需要理解其具体的并行机制。
核心要点
Parallel.ForEachAsync 会并行执行异步操作,但它不是通过创建大量线程来实现,而是通过 任务并行 的方式,利用线程池高效地并发处理多个异步操作。
基本用法
csharp
using var httpClient = new HttpClient();
var urls = new[]
{
"https://api.example.com/1",
"https://api.example.com/2",
"https://api.example.com/3"
};
// 并行处理多个异步操作
await Parallel.ForEachAsync(urls, async (url, cancellationToken) =>
{
var response = await httpClient.GetStringAsync(url, cancellationToken);
Console.WriteLine($"处理完成: {url}, 长度: {response.Length}");
});控制并行度
可以通过 ParallelOptions 设置最大并行度:
csharp
var options = new ParallelOptions
{
MaxDegreeOfParallelism = 3, // 最多同时处理3个操作
CancellationToken = cancellationToken
};
await Parallel.ForEachAsync(items, options, async (item, token) =>
{
await ProcessItemAsync(item, token);
});重要特性
并行执行:多个迭代会同时执行(受
MaxDegreeOfParallelism限制)异步友好:专门设计用于异步委托,不会阻塞线程
线程池利用:底层使用
Task和线程池,不会为每个操作创建专用线程顺序不保证:处理完成的顺序与输入顺序无关
与 Task.WhenAll 的区别
csharp
// Parallel.ForEachAsync - 控制并发度,适合大量操作
await Parallel.ForEachAsync(items,
new ParallelOptions { MaxDegreeOfParallelism = 10 },
async (item, token) => await ProcessAsync(item));
// Task.WhenAll - 全部并发,无并发度控制
await Task.WhenAll(items.Select(item => ProcessAsync(item)));注意事项
委托必须是异步的(返回
ValueTask或Task)默认并行度是环境处理器数,但实际并发数受线程池调度影响
适用于 I/O 密集型操作(如 HTTP 请求、数据库查询)
CPU 密集型操作建议使用
Parallel.ForEach
总之,Parallel.ForEachAsync 确实实现了并行处理,并且是以一种高效、可扩展的方式管理大量异步操作的并发执行。