Explain `async` and `await` keywords in C#.
4 minintermediate.NETasync-awaitconcurrency
Quick Answer
`async` marks a method as asynchronous so it can use `await`; `await` suspends the method until the awaited task completes and returns control to the caller without blocking the thread. When the task finishes, execution resumes after the await point. Async methods should return `Task`/`Task<T>` (avoid `async void` except for event handlers) and are named with an `Async` suffix by convention.
Detailed Answer
async is a modifier that marks a method as asynchronous, indicating it can contain asynchronous operations.
await is an operator that suspends the execution of an async method until the awaited task completes, without blocking the thread.
How it works:
- When
awaitis encountered, the method returns control to its caller - The thread is freed to do other work
- When the awaited task completes, execution resumes from where it left off
Example:
// Basic async/await example
public class DataService
{
// Async method must return Task, Task, or void (avoid void except for event handlers)
public async Task GetDataAsync()
{
// Simulate a network call or database operation
await Task.Delay(2000); // Non-blocking delay
return "Data retrieved successfully";
}
public async Task CalculateAsync(int x, int y)
{
// Simulate CPU-intensive work
await Task.Run(() =>
{
Thread.Sleep(1000);
});
return x + y;
}
}
// Calling async methods
public class Program
{
public static async Task Main(string[] args)
{
var service = new DataService();
Console.WriteLine("Starting async operation...");
// await suspends execution until GetDataAsync completes
string result = await service.GetDataAsync();
Console.WriteLine(result);
// Multiple async operations
int sum = await service.CalculateAsync(5, 10);
Console.WriteLine($"Sum: {sum}");
}
}
// Real-world example: Fetching data from an API
public class WeatherService
{
private readonly HttpClient httpClient = new HttpClient();
public async Task GetWeatherAsync(string city)
{
try
{
Console.WriteLine($"Fetching weather for {city}...");
// await makes the HTTP call non-blocking
string response = await httpClient.GetStringAsync(
$"https://api.weather.com/forecast?city={city}"
);
Console.WriteLine("Weather data received");
return response;
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
return null;
}
}
// Processing multiple cities concurrently
public async Task<List> GetWeatherForMultipleCitiesAsync(List cities)
{
var tasks = cities.Select(city => GetWeatherAsync(city));
// Wait for all tasks to complete
string[] results = await Task.WhenAll(tasks);
return results.ToList();
}
}
// Usage
var weatherService = new WeatherService();
var cities = new List { "New York", "London", "Tokyo" };
var weatherData = await weatherService.GetWeatherForMultipleCitiesAsync(cities);
Key Points:
asyncmethods should be named with theAsyncsuffix by conventionawaitcan only be used insideasyncmethodsasync voidshould be avoided (except for event handlers) - useasync Taskinstead- Exception handling works naturally with try/catch blocks