下面给你一份 《使用 .NET 标准库实现多任务并行处理的详细过程(最完整教程)》,完全基于 .NET Standard / .NET Core / .NET 5–8 通用的标准库 API(无任何第三方库)。
内容包括 Task、线程池、Parallel、同步机制、最佳实践等,全栈可用。
⭐ 一、.NET 标准库并行能力总览
.NET 提供以下标准库用来实现并行程序:
| 技术 | 命名空间 | 场景 |
|---|---|---|
| Task / async-await | System.Threading.Tasks | 现代异步与并行任务 |
| Task.Run() | System.Threading.Tasks | 线程池后台任务 |
| Parallel.For / Parallel.ForEach | System.Threading.Tasks.Parallel | CPU 密集型循环并行 |
| ThreadPool | System.Threading | 超低级手动控制线程池 |
| Thread | System.Threading | 最底层线程控制 |
| 锁(lock, Monitor) | System.Threading | 多线程同步 |
| 并发集合 | System.Collections.Concurrent | 安全数据结构 |
👇 以下将手把手深入讲解。
⭐ 二、最推荐的方式:Task + async/await
✔ 1. 启动一个后台任务
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
Task task = Task.Run(() =>
{
Console.WriteLine("运行任务...");
});
await task;
Console.WriteLine("任务完成");
}
}
✔ 使用线程池
✔ 自动调度
✔ 最佳实践
✔ 2. 带返回值的任务
Task<int> task = Task.Run(() =>
{
return 123;
});
int result = await task;
Console.WriteLine(result);
✔ 3. 多个任务并行执行(WhenAll)
var tasks = new[]
{
Task.Run(() => DoWork(1)),
Task.Run(() => DoWork(2)),
Task.Run(() => DoWork(3))
};
await Task.WhenAll(tasks);
Console.WriteLine("所有任务完成");
✔ 4. 多任务并行 + 返回值
var tasks = Enumerable.Range(1, 5)
.Select(i => Task.Run(() => i * 10));
int[] results = await Task.WhenAll(tasks);
Console.WriteLine(string.Join(",", results));
⭐ 三、Parallel.For / Parallel.ForEach(CPU 密集型)
适用:
✔ 图像处理
✔ 数据处理
✔ CPU 计算
✔ 批量任务并行
✔ Parallel.For
Parallel.For(0, 10, i =>
{
Console.WriteLine($"任务 {i} 在线程 {Task.CurrentId}");
});
✔ Parallel.ForEach
var list = Enumerable.Range(1, 10);
Parallel.ForEach(list, i =>
{
Console.WriteLine($"处理 {i}");
});
特点:
✔ 使用多个 CPU 核心
✔ 自动负载均衡
✔ 自动线程池调度
⭐ 四、Task + Parallel 混合使用(企业级常用)
await Task.Run(() =>
{
Parallel.ForEach(files, file =>
{
ProcessFile(file);
});
});
✔ 将 CPU 密集任务丢到后台
✔ Parallel 在内部使用多核执行
⭐ 五、线程池(ThreadPool)
如果你需要更底层:
ThreadPool.QueueUserWorkItem(_ =>
{
Console.WriteLine("线程池任务");
});
适用:
✔ 高性能后台执行
✔ 不关心返回值
✔ 极轻量
一般不推荐直接用,Task 已经封装得足够好。
⭐ 六、Thread(最底层,不建议常用)
var thread = new Thread(() =>
{
Console.WriteLine("新线程执行");
});
thread.Start();
thread.Join();
适用:
✔ 极特殊情况
✔ 必须指定 STA/MTA
✔ 必须真实操作线程生命周期
平常用 Task 就够了。
⭐ 七、线程同步(lock、Monitor)
当多个任务访问共享变量时要加锁。
private static object locker = new object();
private static int counter = 0;
Parallel.For(0, 10000, i =>
{
lock (locker)
{
counter++;
}
});
线程安全输出:
Console.WriteLine(counter);
⭐ 八、使用并发集合(推荐替代锁)
.NET 标准库提供线程安全集合:
- ConcurrentDictionary
- ConcurrentQueue
- ConcurrentBag
- ConcurrentStack
示例:
var dict = new ConcurrentDictionary<int, string>();
Parallel.For(0, 100, i =>
{
dict[i] = $"Value {i}";
});
无需加锁 → 性能高。
⭐ 九、完整案例:多任务爬取网页(并行 + IO 异步)
static async Task Main()
{
var urls = new[]
{
"https://example.com",
"https://google.com",
"https://microsoft.com"
};
var tasks = urls.Select(async url =>
{
using var http = new HttpClient();
string html = await http.GetStringAsync(url);
Console.WriteLine($"{url} 大小 = {html.Length}");
return html.Length;
});
int[] results = await Task.WhenAll(tasks);
Console.WriteLine("全部完成,总字节数:" + results.Sum());
}
✔ 完全并行
✔ 自动控制并行度
✔ 全 IO 异步
✔ 可跨平台
⭐ 十、最佳实践总结
| 场景 | 推荐方式 |
|---|---|
| 普通后台任务 | Task.Run |
| 等待多个任务完成 | Task.WhenAll |
| CPU 密集型循环 | Parallel.For / Parallel.ForEach |
| 高级、稳健并行计算 | Task + Parallel |
| 修改共享变量 | lock / 并发集合 |
| 超底层控制 | ThreadPool / Thread |
发表回复