C# & .NET

Understanding Async, Await, and Tasks in C#

Asynchrony is about waiting efficiently, not making every operation run on a new thread.

1 min read Beginner 16 min
C#Async.NET

// you will learn

  • Explain Task and await
  • Compose independent asynchronous operations
  • Propagate cancellation

What a Task represents

A Task<T> represents the eventual completion of an operation producing T. An asynchronous I/O operation can wait without occupying a thread for the entire wait. await resumes the method when the operation completes; it does not magically parallelize the method.

Start independent work before awaiting

public async Task<string[]> LoadBothAsync(
    HttpClient client, CancellationToken token)
{
    Task<string> first = client.GetStringAsync("/api/first", token);
    Task<string> second = client.GetStringAsync("/api/second", token);
    return await Task.WhenAll(first, second);
}

The two HTTP operations are started before either result is awaited. Task.WhenAll completes when both complete. With shared state or rate-limited services, concurrency must be bounded rather than expanded without limit.

Handle failure and cancellation

Pass a cancellation token through every layer that supports it. Catch an exception only where you can recover or add meaningful context. Avoid .Result and .Wait() on an async call path: blocking wastes threads and can deadlock in synchronization-context environments.

I/O-bound is not CPU-bound

CPU-heavy calculation still uses a thread. Task.Run can keep a desktop UI responsive, but it does not turn CPU work into free capacity on a web server. Measure the bottleneck before choosing concurrency.

Exercise

Add a five-second timeout using CancellationTokenSource. Test a successful call, one failing endpoint, and cancellation. Explain what happens to the other operation if one faults.

// the notebook, by email

Learn alongside me.

Engineering ideas worth understanding.