# async and await — C#/.NET

Source: https://www.skillbyai.com/en/dotnet/a-await

> Write asynchronous methods with Task and await without blocking threads.

## Waiting without blocking

Most server and UI work waits on I/O: HTTP calls, database queries, files. **`async`/`await`** lets a method wait for that I/O **without blocking a thread**. An `async` method returns **`Task`** (no result), **`Task<T>`** (a result) or occasionally `ValueTask<T>`. When execution reaches `await` on an operation that has not completed, the method **returns to its caller** and the thread is freed to do other work; when the operation completes, the rest of the method resumes, possibly on a different thread pool thread. The compiler rewrites the method into a state machine to make this possible. The rules: use **`async` all the way** up the call chain; never block on tasks with `.Result` or `.Wait()`, which wastes threads and can deadlock in some contexts; avoid `async void` except for event handlers, because exceptions from it cannot be caught by the caller; and name async methods with an `Async` suffix.

## The thread is released while waiting

At await the thread goes back to the pool; when I/O completes, a thread picks up the rest of the method.

![A timeline with a thread bar that stops at a pause marker, a dotted waiting span for I/O, and a second thread bar resuming afterwards.](assets/figures/dotnet/section-6-map.svg) — Figure 6.1 — An async method yields its thread during I/O.

## Calling an API asynchronously

`await` unwraps the result and rethrows exceptions as if the code were synchronous.

```cs
using System.Net.Http.Json;

var http = new HttpClient { BaseAddress = new Uri("https://api.example.com/") };

try
{
    var user = await GetUserAsync(http, 42);
    Console.WriteLine(user?.Name ?? "not found");
}
catch (HttpRequestException ex)
{
    Console.WriteLine($"Request failed: {ex.StatusCode}");
}

static async Task<User?> GetUserAsync(HttpClient http, int id)
{
    using var response = await http.GetAsync($"users/{id}");
    if (response.StatusCode == System.Net.HttpStatusCode.NotFound) return null;
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadFromJsonAsync<User>();
}

record User(int Id, string Name);
```

## Async is not parallel by itself

Awaiting three calls one after another still takes the sum of their times. `await` frees the thread; it does not start other work. To run independent operations concurrently, start them first and await them together.

**Quiz:** What happens to the thread when an async method awaits an HTTP call that is still in progress?

- [ ] It sleeps until the call finishes
- [ ] It throws a TimeoutException
- [x] It returns to the thread pool to do other work
- [ ] It spins in a loop checking the result

*Answer:* It returns to the thread pool to do other work. await releases the thread; the remainder of the method resumes when the operation completes.
