Async/Await
Asynchronous programming lets your app do other work while waiting for slow operations (network, disk, database) instead of blocking the thread.
Core Concepts
async— marks a method as asynchronousawait— pauses execution until the awaited task completesTask— represents an asynchronous operation (void return)Task<T>— represents an async operation that returns a value
Basic Example
public static async Task<string> FetchDataAsync(string url)
{
using var client = new HttpClient();
string content = await client.GetStringAsync(url);
return content;
}
// Calling async code
string html = await FetchDataAsync("https://example.com");
Console.WriteLine($"Received {html.Length} characters");
Multiple Async Operations
// Sequential — one after another
string page1 = await FetchDataAsync("https://api.example.com/1");
string page2 = await FetchDataAsync("https://api.example.com/2");
// Parallel — both at once (faster!)
Task<string> task1 = FetchDataAsync("https://api.example.com/1");
Task<string> task2 = FetchDataAsync("https://api.example.com/2");
string[] results = await Task.WhenAll(task1, task2);
Async File I/O
// Reading
string content = await File.ReadAllTextAsync("data.txt");
// Writing
await File.WriteAllTextAsync("output.txt", "Hello async world!");
// Reading lines
string[] lines = await File.ReadAllLinesAsync("log.txt");
Common Pitfalls
1. Async void — avoid it:
// BAD — exceptions are unobservable
async void DoWork() { ... }
// GOOD — return Task
async Task DoWorkAsync() { ... }
Only use async void for event handlers.
2. Blocking on async code — causes deadlocks:
// BAD — can deadlock in UI/ASP.NET
var result = FetchDataAsync(url).Result;
// GOOD — await it
var result = await FetchDataAsync(url);
3. Not using ConfigureAwait in libraries:
// In library code, avoid capturing sync context
var data = await client.GetStringAsync(url)
.ConfigureAwait(false);