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 5: Asynchronous Programming with C#

The .NET task asynchronous programming (TAP) model, which uses the async and await keywords, was introduced in .NET Framework 4.5. The C# language’s support for these keywords was released at the same time in C# 5. Now, a decade later, the TAP model is an integral part of most .NET developers’ toolsets.

This chapter will explain asynchronous programming in C#, explore how to use Task objects, and delve into best practices of using async and await for I/O-bound and CPU-bound scenarios with .NET.

In this chapter, you will learn about the following:

  • More about asynchronous programming in .NET
  • Working with Task objects
  • Interop with synchronous code
  • Working with multiple background tasks
  • Asynchronous programming best practices

By the end of this chapter, you will have a deeper understanding of asynchronous programming and should feel confident enough to add advanced async features to your team...

Technical requirements

In this chapter, we will be using the .NET command-line interface (CLI) and Visual Studio Code to build and run the sample projects. To follow along with the examples, the following software is recommended:

  • Visual Studio Code version 1.65 or later
  • .NET 6 or later

While these are recommended, if you have .NET 6 installed, you can use your preferred editor. For example, Visual Studio 2022 version 17.0 or later if you are using Windows 10 or 11, Visual Studio 2022 for Mac on macOS 10.13 or later, or JetBrains Rider 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/chapter05.

Let’s get started by working our way through some examples that use the TAP model with async and await.

More about asynchronous programming in .NET

There are two types of scenarios where async code is usually introduced:

  • I/O-bound operations: These involve resources fetched from the network or disk.
  • CPU-bound operations: These are in-memory, CPU-intensive operations.

In this section, we will create some real-world examples that use async and await for each type of operation. Whether you are waiting for an external process to complete or performing CPU-intensive operations within your application, you can leverage asynchronous code to improve your application’s performance.

Let’s start by looking at some examples of I/O-bound operations.

I/O-bound operations

When you are working with I/O-bound code that is constrained by file or network operations, your code should use async and await to wait for the operations to complete.

The .NET methods to perform network and file I/O are asynchronous, so the use of Task.Run will not be necessary:

...

Working with Task objects

Working directly with Task objects can be extremely useful when introducing threading to existing projects. As we saw in the previous section, it is important to update the entire call stack when introducing async and await. On a large code base, those changes could be extensive and would require quite a bit of regression testing.

You can instead use Task and Task<TResult> to wrap the existing methods that you want to run asynchronously. Both Task types represent the asynchronous work being done by a method or action. You use Task when a method would have otherwise returned void. Use Task<TResult> with methods that have a non-void return type.

Here are examples of two synchronous method signatures and their async equivalents:

public interface IAsyncExamples
{
    void ProcessOrders(List<Order> orders);
    Task ProcessOrdersAsync(List<Order> orders);
    ...

Interop with synchronous code

When working with existing projects and introducing async code to the system, there will be points where synchronous and asynchronous code intersect. We have already seen some examples of how to handle this interop in this chapter. In this section, we will focus on that interop in both directions: sync calling async and async calling sync.

We will create a sample project with classes containing synchronous methods representing legacy code and another set of classes with modern async methods.

Let’s start by discussing how to consume async methods in your legacy synchronous code.

Executing async from synchronous methods

In this example, we will be working with a .NET console application that gets a patient and their list of medications. The application will call a synchronous GetPatientAndMedications method that in turn calls an async GetPatientInfoAsync method:

  1. Start by creating a new .NET console application
  2. Add Patient...

Working with multiple background tasks

In this section, we will see code samples for loading data from multiple sources in parallel, not waiting until the method is ready to return the data to the caller. The technique is slightly different for synchronous and asynchronous code, but the general idea is the same.

First, review this method that calls three async methods and uses Task.WhenAll to wait before returning the patient data:

public async Task<Patient> LoadPatientAsync(int patientId)
{
    var taskList = new List<Task>
    {
        LoadPatientInfoAsync(patientId),
        LoadProviderAsync(patientId),
        LoadMedicationsAsync(patientId)
    };
    await Task.WhenAll(taskList.ToArray());
    _patient.Medications...

Asynchronous programming best practices

When working with async code, there are many best practices of which you should be aware. In this section, we will list the most important ones to remember in your day-to-day development. David Fowler, who is a veteran member of the ASP.NET team at Microsoft and a .NET expert, maintains an open source list of many other best practices. I recommend bookmarking this page for later reference while working with your own projects: https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md#asynchronous-programming.

These are my top recommendations (in no particular order) to follow when working with async code:

  1. Always prefer async and await over synchronous methods and blocking calls such as Wait() and Result. If you are creating a new project, you should build with async in mind from the start.
  2. Unless you are using Task.WhenAll to wait for multiple operations simultaneously, you should directly await a...

Summary

In this chapter, we have covered quite a bit of information about asynchronous development with C# and. NET. We started by covering some of the ways to handle I/O-bound and CPU-bound operations in your applications.

Next, we created some practical examples that use the Task and Task<TResult> classes and discovered how to work with multiple Task objects. You got some practical advice for interop between modern asynchronous code and legacy synchronous methods. Finally, we covered some of the most important rules to remember when working with asynchronous code and Task objects.

In the next chapter, Chapter 6, you will learn the ins and outs of parallel programming in .NET using the Task Parallel Library (TPL) and learn how to the avoid common pitfalls of parallel programming.

Questions

  1. Which property of Task makes a blocking call to return data from the underlying method?
  2. Which async method of the Task class should be used to await multiple tasks?
  3. What is the blocking equivalent of Task.WhenAll()?
  4. What type should an async method always return?
  5. Are async methods more suited to I/O-bound or CPU-bound operations?
  6. True or false: Async methods should never end with Async as their suffix.
  7. What method can be used to wrap a synchronous method in an async call?
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 $15.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