Is this use of Parallel.ForEach thread safe?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Parallel.ForEach in .NET is safe as a framework primitive, but your loop body can still be unsafe if it touches shared mutable state. Most bugs come from race conditions in counters, lists, and mutable objects captured by closures. This guide explains how to evaluate safety and how to write Parallel.ForEach code that remains correct under concurrency.
Core Topic Sections
What is thread-safe and what is not
Parallel.ForEach itself handles partitioning and scheduling correctly. Safety problems usually come from what happens inside each iteration.
Safe by default:
- Pure calculations on local variables.
- Independent writes to unique array indexes.
Unsafe by default:
- Incrementing shared counters without atomic operations.
- Writing to a shared list collection without synchronization.
- Mutating shared non-thread-safe objects.
Classic unsafe pattern
The result may vary run to run because multiple threads read and write total concurrently.
Fix shared counters with Interlocked
Interlocked operations are atomic and ideal for simple numeric accumulators.
Prefer thread-local accumulation for performance
Atomic operations are safe, but heavy contention can reduce throughput. Use local accumulators and combine at the end.
This often scales better for aggregation-heavy workloads.
Use concurrent collections for shared output
If each iteration produces output items, do not push into a normal shared list directly. Use concurrent collections or merge per-thread buffers.
ConcurrentBag is good for unordered accumulation.
Determinism and ordering concerns
Parallel.ForEach does not guarantee processing order or output order. If order matters, either:
- Store outputs with original index and sort afterward.
- Use sequential processing for order-sensitive workflows.
Correctness is more important than raw parallel speed for deterministic pipelines.
Exception behavior
Exceptions from parallel loop bodies are aggregated and rethrown as AggregateException.
Pattern:
Do not swallow exceptions silently, otherwise partial work can hide failures.
Avoid over-parallelization
Not every loop benefits from parallel execution. It can hurt performance when:
- Per-item work is tiny.
- Loop body is I/O bound with blocking calls.
- Shared contention dominates computation.
Measure before and after using realistic datasets and production-like environments.
Practical thread-safety checklist
Before shipping Parallel.ForEach code:
- Identify every captured variable in the loop body.
- Verify each shared write is atomic or synchronized.
- Replace non-thread-safe collections with safe alternatives.
- Add concurrency stress tests for flaky race detection.
This checklist catches most failures early.
Common Pitfalls
- Assuming
Parallel.ForEachmakes unsafe loop bodies safe automatically. - Updating shared counters with plain increment operations.
- Writing to a normal shared list from multiple threads without protection.
- Expecting deterministic iteration order from parallel execution.
- Parallelizing very small workloads and regressing performance.
Summary
- '
Parallel.ForEachis safe infrastructure, but loop body safety is your responsibility.' - Use
Interlocked, thread-local reduction, and concurrent collections. - Treat ordering as non-deterministic unless explicitly reconstructed.
- Handle
AggregateExceptioncorrectly for reliable diagnostics. - Benchmark and stress test to confirm both correctness and performance.
Related reading
- Is Thread.Sleep1 special?
- is using an an async lambda with Task.Run redundant?
- Is using async componentDidMount good?
- Is Work Stealing always the most appropriate user-level thread scheduling algorithm?
- Is Using .NET 4.0 Tuples in my C Code a Poor Design Decision?
- Is using Random and OrderBy a good shuffle algorithm?
- IsAsync has no effect for slow property?
- Isn't a synchronous call just an asynchronous call with a small timeout value?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.