Parallel.ForEach 是 .NET Framework 4.0 引入的并行编程功能的一部分,位于 System.Threading.Tasks 命名空间中。它允许你对集合中的元素进行并行处理,可以显著提高处理大量数据时的性能。
基本用法
csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 基本形式
Parallel.ForEach(numbers, number =>
{
Console.WriteLine($"Processing {number} on thread {Thread.CurrentThread.ManagedThreadId}");
// 处理逻辑
});
}
}
高级用法
1. 带分区器的 Parallel.ForEach
csharp
Parallel.ForEach(numbers, new ParallelOptions { MaxDegreeOfParallelism = 4 }, number =>
{
Console.WriteLine($"Processing {number} with MaxDegreeOfParallelism = 4");
});
2. 使用 ParallelOptions 控制并行度
csharp
var options = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount * 2, // 限制最大并行度
CancellationToken = cancellationTokenSource.Token // 取消支持
};
Parallel.ForEach(numbers, options, number =>
{
// 处理逻辑
});
3. 带本地初始化和最终合并
csharp
Parallel.ForEach<int, long>(numbers,
() => 0, // 本地初始化
(number, loopState, localSum) =>
{
// 处理逻辑并返回本地状态
localSum += number;
return localSum;
},
(finalSum) =>
{
// 最终合并
Console.WriteLine($"Partial sum: {finalSum}");
Interlocked.Add(ref totalSum, finalSum);
});
重要参数和特性
- MaxDegreeOfParallelism:控制最大并行任务数
- CancellationToken:支持取消操作
- 分区策略:自动将集合划分为多个分区,默认使用范围分区
- 异常处理:并行循环中的异常会被收集到 AggregateException 中
注意事项
- 线程安全:确保对共享资源的访问是线程安全的
- 顺序不保证:处理顺序与集合顺序无关
- 资源消耗:过度并行化可能导致性能下降
- 异常处理:需要适当处理 AggregateException
性能考虑
csharp
// 测量并行与非并行版本的性能差异
Stopwatch stopwatch = Stopwatch.StartNew();
// 并行版本
Parallel.ForEach(numbers, number =>
{
// 耗时操作
});
stopwatch.Stop();
Console.WriteLine($"Parallel version took {stopwatch.ElapsedMilliseconds} ms");
实际应用示例
csharp
// 处理大量文件
string[] files = Directory.GetFiles(@"C:\LargeFolder");
Parallel.ForEach(files, file =>
{
try
{
ProcessFile(file);
}
catch (Exception ex)
{
Console.WriteLine($"Error processing {file}: {ex.Message}");
}
});
替代方案比较
- Parallel.ForEach:适用于数据并行场景,自动分区
- Task.WhenAll:适用于异步操作,更灵活的控制
- PLINQ:适用于查询场景,语法更简洁
总结
Parallel.ForEach 是处理可并行化集合操作的强大工具,特别适合 CPU 密集型任务。正确使用时可以显著提高性能,但需要注意线程安全、资源管理和异常处理等问题。
