Parallel.For

Note: Use Interlocked to execute atomic operations which will avoid multiple threads modifying a variable simultaneously.

Parallel.For

  • Returns a System.Threading.Tasks.ParallelLoopResult object that includes information such as last iteration completed
  • Throws System.AggregateException if one or more exceptions occur on the threads.
long totalSize = 0;
string[] files = Directory.GetFiles(path);


var result = Parallel.For(0, // The starting element index
    files.Length, // The ending element index
    // An `Action<int>` delegate that takes the current iteration (supplied by the runtime) as its value
    index => 
    {
        FileInfo fi = new(files[index]);
        long size = fi.Length;
        Interlocked.Add(ref totalSize, size);
    });

Parallel.ForEach

Example

var primeNumbers = new ConcurrentBag<int>();

Parallel.ForEach(numbers, number =>
{
    if (isPrime(number))
    primeNumbers.Add(number);
});

To use Parallel.ForEach with a non-generic collection, use Enumerable.Cast to convert the collection to generic:

Parallel.ForEach(somenon-genericCollection.Cast<object>(), currentElement =>
{
    // …
});

Parallel.ForEachAsync

Example:

public class GitHubUser
{
    public string Name { get; set; }
    public string Bio { get; set; }
}

var userHandlers = new[] { "users/okyrylchuk", "users/shanselman", "users/jaredpar", "users/davidfowl" };

using HttpClient client = new() { BaseAddress = new Uri("api.github.com") };

client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("DotNet", "6"));

ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = 3 };

await Parallel.ForEachAsync(userHandlers, parallelOptions, async (uri, token) =>
{
    var user = await client.GetFromJsonAsync<GitHubUser>(uri, token);
    Console.WriteLine($"Name: {user.Name}\nBio: {user.Bio}\n");
});