How to write asynchronous C# with async and await
Write asynchronous C#: define async methods returning Task, await without blocking, run work concurrently with Task.WhenAll, support cancellation tokens, and avoid common async pitfalls.
How async and await work in C#
C# models asynchronous work with the Task type and the async and await keywords. An await suspends the method until the awaited task completes, freeing the thread to do other work instead of blocking. This is ideal for I/O such as network and disk, letting a server handle many requests with few threads.
Prerequisites
- A recent .NET SDK
- Comfort with basic C# syntax
Steps
1. Write an async method
Mark the method async and return Task or Task<T>.
async Task<string> FetchAsync(string url)
{
using var client = new HttpClient();
return await client.GetStringAsync(url);
}
2. Await without blocking
Use await to get the result. Avoid .Result or .Wait(), which block the thread and can deadlock.
string body = await FetchAsync("https://example.com");
3. Run tasks concurrently with WhenAll
Start tasks without awaiting each immediately, then await them together.
var tasks = urls.Select(FetchAsync);
string[] bodies = await Task.WhenAll(tasks);
This runs the requests concurrently rather than one after another.
4. Cancel with CancellationToken
Accept a CancellationToken and pass it down so callers can cancel.
async Task WorkAsync(CancellationToken ct)
{
await Task.Delay(1000, ct);
}
5. Handle exceptions in async code
Exceptions from awaited tasks surface at the await, so wrap it in try-catch as usual.
try { await FetchAsync(url); }
catch (HttpRequestException ex) { Log(ex); }
6. Avoid common async pitfalls
Do not use async void except for event handlers; prefer async Task. Do not block on async code. Flow the cancellation token through the whole call chain.
Verification
Write a method that fetches several URLs sequentially, then with Task.WhenAll, and time both. Confirm the concurrent version is faster. Cancel a long delay with a token and confirm an OperationCanceledException is raised.
Next Steps
Explore IAsyncEnumerable for async streams, ValueTask for hot paths, ConfigureAwait in libraries, and Channel<T> for producer-consumer pipelines.
Prerequisites
- .NET SDK installed
- Basic C# syntax
Steps
- 1Write an async method
- 2Await without blocking
- 3Run tasks concurrently with WhenAll
- 4Cancel with CancellationToken
- 5Handle exceptions in async code
- 6Avoid common async pitfalls