`Parallel.ForEachAsync` (.NET 6+) Controlled Concurrency
1Concept
`Parallel.ForEachAsync` executes asynchronous operations over collections with bounded concurrency, avoiding ThreadPool overload compared to `Task.WhenAll` on huge datasets.
2Architecture Diagram
[ 10,000 URLs to Scrape ]
│
Parallel.ForEachAsync(MaxDegreeOfParallelism: 8)
│
[ 8 Active Worker Pipelines (Locks bounded memory and network socket usage!) ]3Code Example
C# 13 & .NET 9
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class ParallelForEachAsyncDemo
{
public static async Task Main()
{
List<int> jobIds = [1, 2, 3, 4, 5, 6, 7, 8];
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 4 // Max 4 concurrent operations
};
await Parallel.ForEachAsync(jobIds, parallelOptions, async (jobId, ct) =>
{
await Task.Delay(15, ct);
Console.WriteLine($"Completed Job #{jobId} on Thread {Environment.CurrentManagedThreadId}");
});
Console.WriteLine("All batch jobs completed successfully.");
}
}4Expected Output
Completed Job #1 on Thread 4 Completed Job #2 on Thread 6 Completed Job #3 on Thread 7 Completed Job #4 on Thread 8 Completed Job #5 on Thread 4 Completed Job #6 on Thread 6 Completed Job #7 on Thread 7 Completed Job #8 on Thread 8 All batch jobs completed successfully.
5Key Takeaways
- ✓`Parallel.ForEachAsync` replaces custom semaphore throttling loops.
- ✓Always pass `CancellationToken` to enable graceful shutdown.
- ✓Bounds memory usage when processing millions of stream items.