liveBook · Manning

Parallel

As explained in C# Concurrency: Asynchronous and multithreaded programming

Parallel is a .NET class that provides static methods for executing delegates and loop iterations concurrently.

Parallel replaces thread-creation and task-collection boilerplate with static methods for concurrent delegates and loop iterations. Invoke runs delegates; For and ForEach parallelize synchronous loops; ForEachAsync accepts an asynchronous body and returns a Task that completes after all iterations finish. section 8.1.4

ForEach is a small change from ordinary iteration, but its workload still needs sensible limits. Parallel supports cancellation, custom schedulers, and MaxDegreeOfParallelism; choosing that maximum is a central performance concern, especially for large collections. section 8.1.4 section 8.3

Mail merge

A mail-merge operation can process recipients with Parallel.ForEach, constructing each message and sending it independently. The example catches failures per recipient and logs the failed address rather than allowing one send to define the whole operation.

Listing 8.9 Parallel.ForEach performance benchmark
for (int j = 0; j < 5; ++j)
{
  var items = Enumerable.Range(0, 1000).ToArray();
  var sw = Stopwatch.StartNew();
  Parallel.ForEach(items, 
     (item)=>Thread.Sleep(1000));
  sw.Stop();
  Console.WriteLine(sw.ElapsedMilliseconds);
}

Benchmark Parallel.ForEach over 1,000 one-second delays to observe completion time and evaluate an appropriate concurrency level. section 8.1.4

Listing 8.10 Asyncronous mail merge with the Parallel class
void MailMerge(
   string from,
   string subject,
   string text, 
   (string email,string name)[] recipients)
{
   var processingTasks = new Task[recipients.Length];
   Parallel.ForEachAsync(recipients,                        #1
      new ParallelOptions { 
         MaxDegreeOfParallelism= recipients.Length          #2
      },
      async (current,_) =>                                  #3
      {
         try
         {
            var sender = new SmtpClient("smtp.example.com");
            var message = new MailMessage();
            message.From = new MailAddress(from);
            message.Subject = subject;
            message.To.Add(new MailAddress(current.email));
            message.Body = text.Replace("{name}", current.name);
            await sender.SendMailAsync(message);            #4
         }
         catch
         {
            LogFailure(current.email);
         }
      }).Wait();                                            #5
}

Use Parallel.ForEachAsync when each iteration awaits asynchronous I/O, and configure MaxDegreeOfParallelism deliberately instead of assuming unlimited concurrency is appropriate. section 8.1.4

How C# Concurrency: Asynchronous and multithreaded programming covers it

How deep it goes
Defines four static methods and demonstrates loop usage, performance testing, and concurrency limits, while deferring detailed cancellation and scheduler treatment.
Examples
Uses concurrent mail merge, delayed-iteration benchmarks, and explicit MaxDegreeOfParallelism configurations.
What it assumes
Assumes familiarity with delegates, loops, Tasks, and asynchronous methods while presenting Parallel as simpler coordination syntax.
What you can do after
Apply Parallel.ForEach or Parallel.ForEachAsync to collection work and tune concurrency using a performance test.
How it connects
Ties Parallel to the thread pool, Task, asynchronous code, cancellation, schedulers, and MaxDegreeOfParallelism.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C# Concurrency: Asynchronous and multithreaded programming. The section links point to the parts of the book it draws on.