Parallel.ForEach(myList, item => { ProcessHeavy(item); // 耗时的同步任务 });这个方法会自动帮你分配线程池中的线程去并发执行任务。唯一要注意的是,它不保证顺序,多个任务是同时跑的。如果你访问了共享资源(比如同一个文件、变量),就要手动加锁或用线程安全的方式处理。
await Parallel.ForEachAsync(myList, async (item, token) => { await ProcessAsync(item); // 异步耗时任务,如 HTTP 请求 });这个非常适合需要同时跑多个异步请求,比如发起 100 个 API 调用、同时上传一堆文件等。
.高性能需求场景,如后台服务、图像处理等
var list = new List<int> { 1, 2, 3 }; list.ForEach(item => Console.WriteLine(item));看起来非常简洁,适合快速写小脚本或者 UI 层的简单逻辑处理。但它只支持 List 类型,而且不能用于异步操作。你要是这样写:
list.ForEach(async item => await DoSomethingAsync(item)); // 错误写法!这段代码会变成 async void,出了错都捕不到,调试困难,不建议这样使用。
.代码洁癖患者追求简短写法
foreach (var item in myList) { await DoSomethingAsync(item); // 一个个执行 }虽然不能并发,但非常适合对顺序敏感的场景,比如依次写数据库、依次上传文件、依次记录日志等。
// 堆代码 duidaima.com await foreach (var row in GetDataAsync()) { Console.WriteLine(row); }这类写法适合消息队列、数据库分页加载、SignalR 等场景。
.可配合异步流读取大数据量
遍历方式 | 是否支持并发 | 是否支持异步 | 顺序是否保证 | 支持的集合类型 | 推荐使用场景 |
---|---|---|---|---|---|
Parallel.ForEach | ✅ | ❌ | ❌ | 所有 IEnumerable | 并行处理 CPU 密集型任务 |
Parallel.ForEachAsync | ✅ | ✅ | ❌ | 所有 IEnumerable | 并发处理异步任务(如接口、I/O) |
List<T>.ForEach | ❌ | ❌(⚠不支持) | ✅ | 仅限 List<T> | 小量数据处理,语法简洁 |
foreach + await | ❌ | ✅ | ✅ | 所有 IEnumerable | 顺序异步执行,控制清晰 |
await foreach(异步流) | ❌ | ✅ | ✅ | 异步可枚举对象 | 异步流处理,如数据库流、消息流等 |