ASP.NET Core is built for async I/O. Database calls, HTTP client requests, and file reads use async Task methods with await—similar to JavaScript promises but with compile-time checking.
Basic pattern
public async Task<List<User>> GetUsersAsync() {
return await _db.Users.ToListAsync();
}
Action methods return Task<IActionResult> and await services—Kestrel handles many concurrent requests efficiently.
Rules of thumb
- Suffix async methods with
Async - Await all the way—avoid
.Resultor.Wait()(deadlock risk) - Use
ConfigureAwait(false)in library code; ASP.NET Core doesn't need it in controllers - CPU-bound work may use
Task.Runsparingly—not for every loop
Important interview questions and answers
- Q: async improves throughput how?
A: Threads aren't blocked during I/O waits—they return to the pool until the operation completes. - Q: async void?
A: Avoid except event handlers—exceptions can't be caught by callers; preferasync Task.
Self-check
- Why avoid .Result on async calls in ASP.NET?
- What return type should an async API action use?
Pitfall: Blocking async with .Result or .Wait() can deadlock ASP.NET request threads—await all the way through the call stack.