Lesson 21 of 30
Async / Await and Task-Based Programming
C# in Visual Studio 2026 — a hands-on guide for developers at every level.
Why Async?
I/O operations (network requests, file reads, database queries) can take hundreds of milliseconds. async/await lets your thread do other work while waiting, keeping applications responsive without the complexity of manual threading.
async and await
using System.Net.Http;
static async Task<string> FetchAsync(string url)
{
using var client = new HttpClient();
string content = await client.GetStringAsync(url);
return content[..Math.Min(100, content.Length)]; // first 100 chars
}
string html = await FetchAsync("https://example.com");
Console.WriteLine(html);
Task and Task<T>
| Return type | Use when |
|---|---|
Task | Async method that returns nothing |
Task<T> | Async method that returns a value |
ValueTask<T> | High-performance async (avoid heap allocation) |
Parallel Tasks
static async Task RunParallelAsync()
{
Task<int> t1 = Task.Run(() => HeavyWork(1));
Task<int> t2 = Task.Run(() => HeavyWork(2));
int[] results = await Task.WhenAll(t1, t2);
Console.WriteLine($"Results: {results[0]}, {results[1]}");
}
⚠️ Avoid async void
Only use async void for top-level event handlers. Always use async Task for everything else — async void makes exceptions impossible to catch.