Parallel.For 自动并行但不保序,适用独立迭代;需防共享变量竞争、正确处理 AggregateException、显式传 CancellationToken 实现取消,小数据量或内存带宽瓶颈时性能可能下降。
普通 for 循环是严格串行、按索引递增顺序执行的;Parallel.For 则把迭代范围切分成若干块,交由 ThreadPool 中的多个线程并行处理。这意味着:i 的实际执行顺序完全不可预测,甚至可能 i=100 先于 i=1 完成。
常见错误现象:在循环体里直接修改共享变量(如 sum += array[i]),没加锁或用原子操作,结果随机出错。
迭代完全独立,无读写竞争,比如批量图像缩放、数组元素逐个计算哈希Parallel.ForEach + AsOrdered()(性能代价大,慎用)普通 for 遇到异常立刻中断,堆栈清晰;Parallel.For 中任一线程抛出异常,整个操作会封装为 AggregateException 抛出,内含所有子异常。
典型错误:只用 try-catch(Exception) 捕获,漏掉外层 AggregateException,导致程序崩溃。
try-catch(AggregateException ex),再遍历 ex.InnerExceptions 处理每个子异常ParallelOptions.MaxDegreeOfParallelism 限制并发数,降低异常爆发密度try-catch,避免污染整体执行普通 for 要中断只能靠 break 或条件判断;Parallel.For 支持协作式取消,但必须手动传入 CancellationToken,否则调用 cancellationTokenSource.Cancel() 没反应。
var cts = new CancellationTokenSource();
Parallel.For(0, 1000, new ParallelOptions { CancellationToken = cts.Token }, i =>
{
if (cts.Token.IsCancellationRequested) return;
// 实际工作
});
cts.Cancel(); // 此时正在执行的迭代会继续,新分配的迭代不再启动
CancellationToken 只影响任务调度,不强制终止正在运行的线程(.NET 不支持强行 Abort)Token.IsCancellationRequested 并及时退出,否则无法响应取消ParallelOptions 时,默认无取消支持,Cancel() 完全无效Parallel.For 启动有开销:任务拆分、线程调度、同步协调。对少量迭代(比如 for (i = 0; i )或单次耗时极短的操作(如简单加法),并行反而比普通 for 慢 2–5 倍。
Stopwatch 实测对比,别凭感觉——尤其注意首次运行受 JIT 影响,应预热后测真正难的是识别「哪些迭代能并行」和「哪些共享状态必须保护」,而不是换一个关键字。写完 Parallel.For 后,务必验证结果正确性、异常行为、取消响应和真实负载下的性能表现。