C# / CHAPTER 15

Tasks, asynchronous completion, and failure

Advanced

Return completion handles that callers can actually await.

By the end of this chapter

  • Distinguish Task from async void
  • Combine independent operations
  • Observe failures through await

The idea

A Task represents eventual completion, and Task<T> also carries a result. An async method can run synchronously until it reaches an incomplete await. Awaiting an already completed task need not yield control. Asynchronous does not automatically mean a new thread, and it does not make CPU-heavy work free.

Return Task from ordinary asynchronous operations so callers can await completion and observe exceptions. async void is mainly for event-handler contracts and cannot provide that completion handle. Start independent tasks before awaiting their combination when concurrency is intended. Task.WhenAll preserves input order for successful result arrays and does not automatically cancel remaining work merely because one task fails.

C# example
using System;
using System.Threading.Tasks;
static async Task<int> SumAsync() {
  Task<int> a = Task.FromResult(4);
  Task<int> b = Task.FromResult(7);
  int[] values = await Task.WhenAll(a, b);
  return values[0] + values[1];
}
Console.WriteLine(await SumAsync());
Result
11

Both tasks are combined into one awaitable completion result.

Try it yourself

Write an asynchronous composition that waits for two independent values and propagates either failure.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

Which return type permits a caller to await a save operation that has no result value?