This article explores the key distinctions between Parallel.ForEach
and the Task
family (specifically Task.WhenAll
, Task.Run
, etc.) in C#. Both facilitate concurrent or parallel code execution, but their applications, behaviors, and task handling differ significantly.
Parallel.ForEach:
Parallel.ForEach
, a member of the System.Threading.Tasks
namespace, enables parallel iteration over collections. It automatically distributes workload across available threads within the thread pool, proving highly efficient for CPU-bound operations.
Key Features:
Example:
<code class="language-csharp">using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; Parallel.ForEach(items, item => { // Simulate CPU-intensive task (e.g., complex calculation) Console.WriteLine($"Processing item: {item} on thread {Task.CurrentId}"); }); Console.WriteLine("All items processed."); } }</code>
Tasks (Task.Run, Task.WhenAll):
Task.Run
and Task.WhenAll
offer granular control over asynchronous and parallel execution. While Task.Run
can offload CPU-bound work, it's frequently paired with asynchronous code for I/O-bound tasks.
Key Features:
Task.WhenAll
, Task.WhenAny
).Task.Run
excels in scenarios requiring asynchronous behavior.Example:
<code class="language-csharp">using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; Parallel.ForEach(items, item => { // Simulate CPU-intensive task (e.g., complex calculation) Console.WriteLine($"Processing item: {item} on thread {Task.CurrentId}"); }); Console.WriteLine("All items processed."); } }</code>
Feature | Parallel.ForEach | Task.Run / Task.WhenAll | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Parallel iteration for CPU-bound tasks. | Asynchronous and parallel execution (CPU/I/O). | ||||||||||||||||||||||||
Thread Control |
Less control; uses the thread pool. | Full control over task creation and execution. | ||||||||||||||||||||||||
Execution Type | Synchronous (blocking). | Asynchronous (non-blocking unless awaited). | ||||||||||||||||||||||||
|
CPU-bound tasks (parallel for loop). | General-purpose tasks (CPU-bound or I/O-bound). | ||||||||||||||||||||||||
Parallelism |
Parallelism | Parallel or asynchronous. | ||||||||||||||||||||||||
Parallel.ForEach Error Handling |
Exceptions thrown per iteration. | aggregates exceptions. | ||||||||||||||||||||||||
|
Automatic performance tuning. | Manual task distribution management. |
Use when:Task.Run
Task.WhenAll
I/O-bound tasks are involved.Parallel.ForEach
Task.Run
Granular control over task management, cancellation, or synchronization is needed.Task.WhenAll
The above is the detailed content of Task and Parallel. For more information, please follow other related articles on the PHP Chinese website!