Reader small image

You're reading from  Parallel Programming and Concurrency with C# 10 and .NET 6

Product typeBook
Published inAug 2022
PublisherPackt
ISBN-139781803243672
Edition1st Edition
Right arrow
Author (1)
Alvin Ashcraft
Alvin Ashcraft
author image
Alvin Ashcraft

Alvin Ashcraft is a software engineer and developer community champion with over 25 years of experience in software development. Working primarily with Microsoft Windows, web, and cloud technologies, his career has focused primarily on the healthcare industry. He has been awarded as a Microsoft MVP 11 times, most recently as a Windows Dev MVP. Alvin works in the Philadelphia area for Allscripts, a global healthcare software company, as a principal software engineer. He is also a board member of the TechBash Foundation, where he helps organize the annual TechBash developer conference. He has previously worked for companies such as Oracle, Genzeon, CSC, and ITG Pathfinders. Originally from the Allentown, PA area, Alvin currently resides in West Grove, PA with his wife and three daughters.
Read more about Alvin Ashcraft

Right arrow

Chapter 6: Parallel Programming Concepts

The Task Parallel Library (TPL) encompasses various .NET programming constructs, including parallel loops, parallel invocations, PLINQ, and task-based async programming. In Chapter 5, we explored async programming with Task objects. This chapter will delve deeper into the System.Threading.Tasks.Parallel members in the TPL and some additional tasking concepts for handling related tasks.

The lines between parallel programming, concurrency, and asynchronous programming are not always clear-cut, and you will discover where the three concepts intersect as we read ahead.

In this chapter, you will learn the following:

  • Getting started with the TPL
  • Parallel loops in .NET
  • Relationships between parallel tasks
  • Common pitfalls with parallelism

By the end of this chapter, you will understand how to use parallel programming in your own projects, why you would choose a parallel loop over a standard loop, and when to use async...

Technical requirements

To follow along with the examples in this chapter, the following software is recommended for Windows developers:

  • Visual Studio 2022 version 17.0 or later
  • .NET 6

While these are recommended, if you have .NET 6 installed, you can use your preferred editor. For example, Visual Studio 2022 for Mac on macOS 10.13 or later, JetBrains Rider, or Visual Studio Code will work just as well.

All the code examples for this chapter can be found on GitHub at https://github.com/PacktPublishing/Parallel-Programming-and-Concurrency-with-C-sharp-10-and-.NET-6/tree/main/chapter06.

Let’s get started by discussing the TPL and where it fits within the world of parallel programming in .NET.

Getting started with the TPL

The TPL consists of the types that were added to the System.Threading and System.Threading.Tasks namespaces in .NET Framework 4.0. The TPL provides features that make parallelism and concurrency simpler for .NET developers. There is no need to manage the ThreadPool tasks in your code. The TPL handles thread management and automatically scales the number of active threads based on processor capability and availability.

Developers should use the TPL when they need to introduce parallelism or concurrency to their code for improved performance. However, the TPL is not the right choice for every scenario. How do you know when to choose the TPL and which TPL constructs are the best choice for each scenario?

Let’s explore a few common scenarios.

I/O-bound operations

When dealing with I/O-bound operations such as file operations, database calls, or web service calls, asynchronous programming with Task objects and C# async/await operations are...

Parallel loops in .NET

In this section, we will explore some examples of leveraging data parallelism in .NET projects. The parallel versions of the C# for and foreach loops, Parallel.For and Parallel.ForEach, are part of the System.Threading.Tasks.Parallel namespace. Using these parallel loops is similar to using their standard counterparts in C#.

One key difference is that the body of the parallel loops is declared as a lambda expression. As a result, there are some changes to how you would continue or break from the parallel loops. Instead of using continue to stop the current iteration of the loop without breaking the entire loop, you would use a return statement. The equivalent of using break to break out of a parallel loop is to use the Stop() or Break() statements.

Let’s look at an example of using a Parallel.For loop in a .NET WinForms application.

Basic Parallel.For loops

We are going to create a new WinForms application that allows users to select a folder...

Relationships between parallel tasks

In the previous chapter, Chapter 5, we learned how to use async and await to perform work in parallel and manage the flow of tasks by using ContinueWith. In this section, we will examine some of the TPL features that can be leveraged to manage relationships between tasks running in parallel.

Let’s start by looking deeper into the Parallel.Invoke method provided by the TPL.

Under the covers of Parallel.Invoke

In Chapter 2, we learned how to use the Parallel.Invoke method to execute multiple tasks in parallel. We are going to revisit Parallel.Invoke now and discover what is happening under the covers. Consider using it to invoke two methods:

Parallel.Invoke(DoFirstAction, DoSectionAction);

This is what is happening behind the scenes:

List<Task> taskList = new();
taskList.Add(Task.Run(DoFirstAction));
taskList.Add(Task.Run(DoSectionAction));
Task.WaitAll(taskList.ToArray());

Two tasks will be created and queued...

Common pitfalls with parallelism

When working with the TPL, there are some practices to avoid in order to ensure the best outcomes in your applications. In some cases, parallelism used incorrectly can result in performance degradation. In other cases, it can cause errors or data corruption.

Parallelism is not guaranteed

When using one of the parallel loops or Parallel.Invoke, the iterations can run in parallel, but they are not guaranteed to do so. The code in these parallel delegates should be able to run successfully in either scenario.

Parallel loops are not always faster

We discussed this earlier in this chapter, but it is important to remember that parallel versions of for and foreach loops are not always faster. If each loop iteration runs quickly, the overhead of adding parallelism can slow down your application.

This is important to remember when introducing any threading to applications. Always test your code before and after introducing concurrency or parallelism...

Summary

In this chapter, we learned how to leverage parallel programming concepts in our .NET applications. We got hands-on with Parallel.For, Parallel.ForEach, and Parallel.ForEachAsync loops. In those sections, we learned how to safely aggregate data while maintaining thread safety. Next, we learned how to manage relationships between parent tasks and their parallel children. This will help to ensure your applications maintain an expected order of operations.

Finally, we covered some important pitfalls to avoid when implementing parallelism in our applications. Developers will want to pay close attention to avoid any of these pitfalls in their own applications.

To read more about data parallelism in .NET, the Data Parallelism documentation on Microsoft Docs is a great place to start: https://docs.microsoft.com/dotnet/standard/parallel-programming/data-parallelism-task-parallel-library.

In the next chapter, we will continue our exploration of the TPL by learning how to leverage...

Questions

  1. Which parallel loop executes a delegate in parallel for a given number of iterations?
  2. Which parallel loop is the awaitable version of Parallel.ForEach?
  3. Which parallel method can execute two or more provided actions in parallel?
  4. Which Task.Factory.StartNew option can attach a child task’s completion to its parent?
  5. Which Task.Factory.StartNew option can be provided to a parent task to prevent any child tasks from attaching?
  6. Why should you never use Task.Run when using TaskCreationOptions to establish parent/child relationships?
  7. Are parallel loops always faster than their traditional counterparts?
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Parallel Programming and Concurrency with C# 10 and .NET 6
Published in: Aug 2022Publisher: PacktISBN-13: 9781803243672
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Alvin Ashcraft

Alvin Ashcraft is a software engineer and developer community champion with over 25 years of experience in software development. Working primarily with Microsoft Windows, web, and cloud technologies, his career has focused primarily on the healthcare industry. He has been awarded as a Microsoft MVP 11 times, most recently as a Windows Dev MVP. Alvin works in the Philadelphia area for Allscripts, a global healthcare software company, as a principal software engineer. He is also a board member of the TechBash Foundation, where he helps organize the annual TechBash developer conference. He has previously worked for companies such as Oracle, Genzeon, CSC, and ITG Pathfinders. Originally from the Allentown, PA area, Alvin currently resides in West Grove, PA with his wife and three daughters.
Read more about Alvin Ashcraft