16 Working with asynchronous computations

 

This chapter covers

  • Using Task to represent asynchronous computations
  • Composing asynchronous operations sequentially and in parallel
  • Working with asynchronous sequences

In today’s world of distributed applications, many operations are performed asynchronously. A program may begin some operation that takes a relatively long time, such as requesting data from another application, but it won’t sit idle, waiting for that operation to complete. Instead, it will go on to do other work and resume the operation once the data has been received.

Asynchrony certainly is the bread and butter of today’s programmer. I waited until this late in the book to deal with it because it adds a level of complexity, which I wanted to postpone in order to make the ideas presented so far more approachable.

Asynchronous operations are represented in C# using Task, and in this chapter you’ll see that Task<T> is not so different from other containers, such as Option<T>, Try<T>, and so on. While Task<T> represents a single value that is delivered asynchronously, IAsyncEnumerable<T> is a recent addition to the language that is used to represent a sequence of values that are delivered asynchronously; I’ll discuss this in the second part of this chapter.

16.1 Asynchronous computations

16.1.1 The need for asynchrony

16.1.2 Representing asynchronous operations with Task

16.1.3 Task as a container for a future value

16.1.4 Handling failure

16.1.5 An HTTP API for currency conversion

16.1.6 If it fails, try a few more times

16.1.7 Running asynchronous operations in parallel

16.2 Async streams

16.2.1 Reading from a file as an async stream

16.2.2 Consuming async streams functionally

16.2.3 Consuming data from several streams

16.2.4 Aggregation and sorting with async streams

16.3 Summary