C# and .NETworking

How do you explain async and await without blocking a thread?

Show that await releases the thread, and name the bug you introduce with .Result.

Points worth saying

  • async marks a method that can pause. await registers a continuation.
  • The thread is free while I/O is outstanding.
  • .Result and .Wait() can deadlock a context that expects to resume on the same thread.

A full answer

An async method runs synchronously until the first incomplete await. At that point the method returns a Task to its caller and the current thread goes back to the pool. When the operation completes, the continuation is scheduled.

This is why async helps a web server. A database call that takes 40 milliseconds does not need a thread sitting inside that wait. The thread can serve another request.

Blocking on a Task with .Result or .Wait() removes that benefit. On a context that captures the synchronization context, it can also deadlock: the blocked thread is the thread the continuation needs. In ASP.NET Core there is no classic UI synchronization context, but blocking still wastes threads and hides cancellation.

Propagate async all the way. Accept a CancellationToken and pass it down. Use ConfigureAwait(false) in library code that has no reason to resume on a captured context. In application code on ASP.NET Core, the default is fine.

Example

public async Task<Order?> GetOrderAsync(Guid id, CancellationToken cancellationToken)
{
    return await db.Orders
        .AsNoTracking()
        .FirstOrDefaultAsync(order => order.Id == id, cancellationToken);
}

Mark your progress

Create a practice profile to mark this question.