0

0

c# Parallel.ForEachAsync 的用法和 Task.WhenAll 的区别

畫卷琴夢

畫卷琴夢

发布时间:2026-01-24 11:33:09

|

791人浏览过

|

来源于php中文网

原创

Parallel.ForEachAsync适合带并发度限制的逐项处理,核心是控制MaxDegreeOfParallelism;Task.WhenAll适合全量并发并聚合返回值,无内置限流。选型取决于是否需硬性限流、是否需返回值及数据量大小。

c# parallel.foreachasync 的用法和 task.whenall 的区别

Parallel.ForEachAsync 适合“带并发度限制的逐项处理”

它本质是 foreach 的异步增强版,核心价值在于能控制最大并行数(MaxDegreeOfParallelism),避免瞬间拉起成百上千个 Task 压垮资源。比如调用外部 API、读写文件、数据库批量操作时,你通常不希望无节制并发。

常见错误是误以为它“一定比 Task.WhenAll 快”——其实它只是更可控;如果所有任务彼此完全独立且资源充足,Task.WhenAll 往往启动更快、调度开销更低。

  • 必须传入 IAsyncEnumerable 或可转为它的源(如 list.ToAsyncEnumerable()
  • MaxDegreeOfParallelism 默认是 Environment.ProcessorCount,但对 IO 密集型任务常需手动设为 10–50 级别
  • 无法直接获取每个任务的返回值;若需结果,得在循环体内显式收集到共享集合(注意线程安全)
await Parallel.ForEachAsync(items, new ParallelOptions { MaxDegreeOfParallelism = 8 }, async (item, ct) =>
{
    var result = await CallExternalApiAsync(item, ct);
    // 注意:这里不能直接 return result
    // 需要用 ConcurrentBag 或 lock 保护的 List
    results.Add(result);
});

Task.WhenAll 适合“全量并发 + 收集返回值”

它只做一件事:把一堆 Task 同时启动,并等它们全部完成,最后返回 Task。没有内置并发数限制,也不关心执行顺序。

典型误用是拿它处理几千个 HTTP 请求却不加限流——可能触发连接池耗尽、远程服务限流或 SocketException

  • 输入是 IEnumerable>,所以你要先用 Select 把数据映射成任务: items.Select(x => DoWorkAsync(x))
  • 任一任务失败,整个 Task.WhenAll 就以 AggregateException 失败,需用 await task.ConfigureAwait(false)try/catch 捕获
  • 天然支持返回值聚合,无需额外同步机制
var tasks = items.Select(item => CallExternalApiAsync(item));
var results = await Task.WhenAll(tasks); // results 是 T[]

选哪个?看三个关键点

不用背规则,现场问自己:

网钛淘拍CMS(TaoPaiCMS) V1.60
网钛淘拍CMS(TaoPaiCMS) V1.60

2013年07月06日 V1.60 升级包更新方式:admin文件夹改成你后台目录名,然后补丁包里的所有文件覆盖进去。1.[新增]后台引导页加入非IE浏览器提示,后台部分功能在非IE浏览器下可能没法使用2.[改进]淘客商品管理 首页 列表页 内容页 的下拉项加入颜色来区别不同项3.[改进]后台新增/修改淘客商品,增加淘宝字样的图标和天猫字样图标改成天猫logo图标4.[改进]为统一名称,“分类”改

下载
  • 是否需要硬性限制同时跑几个异步操作?→ 是就用 Parallel.ForEachAsync
  • 是否必须拿到每个操作的返回值,且数量不大(Task.WhenAll
  • 是否要响应取消(CancellationToken)并让所有正在运行的任务及时退出?→ Parallel.ForEachAsyncct 的传播更明确;Task.WhenAll 需确保每个子任务都正确接收并响应 ct

混合场景也常见:先用 Task.WhenAll 并发拉取一批 ID,再用 Parallel.ForEachAsync 分批次处理这些 ID——这时候两者不是互斥,而是分工。

容易被忽略的坑

Parallel.ForEachAsyncMaxDegreeOfParallelism 不是“最小并发数”,它只设上限;实际并发数取决于调度和等待 I/O 的时机,可能长期低于该值。

Task.WhenAll 的数组长度就是任务总数,但如果源数据量极大(比如 10 万条),直接生成 10 万个 Task 会吃掉大量内存和调度开销——这时必须分块,用 Chunk + Task.WhenAll 或改用 Parallel.ForEachAsync

两者都不自动处理重试、超时、降级;这些逻辑得你写在 CallExternalApiAsync 内部,而不是指望并行原语帮你兜底。

相关专题

更多
php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

67

2025.12.04

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

394

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

574

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

482

2023.08.10

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

356

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2076

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

348

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.09.05

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号