Chapter 5. Writing asynchronous code

 

This chapter covers

  • What it means to write asynchronous code
  • Declaring asynchronous methods with the async modifier
  • Waiting asynchronously with the await operator
  • Language changes in async/await since C# 5
  • Following usage guidelines for asynchronous code

Asynchrony has been a thorn in the side of developers for years. It’s been known to be useful as a way of avoiding tying up a thread while waiting for some arbitrary task to complete, but it’s also been a pain in the neck to implement correctly.

Even within the .NET Framework (which is still relatively young in the grand scheme of things), we’ve had three models to try to make things simpler:

  • The BeginFoo/EndFoo approach from .NET 1.x, using IAsyncResult and AsyncCallback to propagate results
  • The event-based asynchronous pattern from .NET 2.0, as implemented by BackgroundWorker and WebClient
  • The Task Parallel Library (TPL) introduced in .NET 4.0 and expanded in .NET 4.5

Despite the TPL’s generally excellent design, writing robust and readable asynchronous code with it was hard. Although the support for parallelism was great, some aspects of general asynchrony are much better fixed in a language instead of purely in libraries.

5.1. Introducing asynchronous functions

5.2. Thinking about asynchrony

5.3. Async method declarations

5.4. Await expressions

5.5. Wrapping of return values

5.6. Asynchronous method flow

5.7. Asynchronous anonymous functions

5.8. Custom task types in C# 7

5.9. Async main methods in C# 7.1

5.10. Usage tips

Summary