Learning hub
C# async and await language primer — async vs await keywords, TAP examples, then links to ASP.NET Core production articles.
How this hub is indexed: This page owns the C# language primer (async/await keywords, TAP examples). Dictionary SERPs and ASP.NET production failure modes live on dedicated articles — linked below.
| You want… | Open |
|---|---|
| asynchronous meaning / definition | Asynchronous meaning |
| async vs sync tables | Async vs sync |
| promise / Task / Future | What is a promise |
| callback vs promise | Callback vs promise |
| ASP.NET Core production checklist | Async/await in ASP.NET Core |
| 504 / idle CPU starvation | Thread pool starvation |
| Task vs Thread | Task vs Thread |
| Task.WhenAll caps | WhenAll vs WaitAll |
| Multithreading map | C# multithreading primer |
Async and await in C# are language features for the Task-based Asynchronous Pattern (TAP). You write code as a normal sequence of statements, but await lets the runtime release the current thread while I/O (SQL, HTTP, files) finishes instead of blocking.
An async method in C# is marked with the async modifier and returns Task or Task<T> so callers can observe completion and exceptions. await is used inside that method on awaitable work (FirstOrDefaultAsync, ReadToEndAsync, SendAsync, …).
This hub is a C# async and await explained primer with examples — keywords and mechanics. For request-path rules (.Result, CancellationToken, WhenAll on DbContext), use the ASP.NET Core async checklist.
async and await are not alternatives — they work together.
async keyword in C# | await keyword in C# | |
|---|---|---|
| What it is | Modifier on a method, lambda, or local function | Operator inside an async method |
| Purpose | Allows await in the body; method returns a Task / Task<T> | Suspends the method until awaited work completes |
| Where it goes | On the method signature: public async Task<T> … | Before an awaitable call: await _db.SaveAsync(ct) |
| Without the other | async with no await → CS4014 (runs synchronously) | await outside async → compile error |
| Analogy | Declares “this method can pause safely” | The actual pause point |
async sets up the method; await is where control returns to the caller until I/O completes.
Three steps for every async method in C#:
async and return Task or Task<T> (not void on APIs).await each I/O call end to end — EF Core, HttpClient, File.*Async, streams.CancellationToken on ASP.NET Core request paths.public async Task<OrderDto?> GetOrderAsync(Guid id, CancellationToken ct)
{
var order = await _db.Orders.FirstOrDefaultAsync(o => o.Id == id, ct);
return order is null ? null : Map(order);
}
| Signature | When to use |
|---|---|
async Task | Async work with no return value (side effects only) |
async Task<T> | Async work that returns T — most API and service methods |
async void | UI event handlers only — never controllers, middleware, or services |
On ASP.NET Core, actions return async Task<IActionResult> or async Task<ActionResult<T>> so Kestrel can track faults and completion.
Task back immediately (work started).await, the method yields — the ThreadPool worker is free for other requests.await.Caller → async method runs → await SQL/HTTP/file → worker returns to pool
→ I/O completes → continuation runs → Task completes with result
Same mechanics for console apps and UI — on APIs the win is concurrency under load, not faster SQL.
Name I/O methods with an Async suffix (GetOrderAsync, ReadConfigAsync) so callers know they must not block with .Result.
| Benefit | Meaning |
|---|---|
| Non-blocking I/O | Worker free during SQL/HTTP waits |
| Readable flow | Linear code instead of nested callbacks |
| Composition | await step A, then step B |
| Not magic speed | I/O duration unchanged — throughput improves |
For callback history and promises: callback vs promise · promise vs Task.
public async Task<string> ReadConfigAsync(string path, CancellationToken ct)
{
await using var reader = new StreamReader(path);
return await reader.ReadToEndAsync(ct);
}
public Task<string> ReadConfigFastAsync(string path, CancellationToken ct) =>
File.ReadAllTextAsync(path, ct);
Task.Delay vs Thread.Sleep (language note)await Task.Delay(...) yields without blocking a worker; Thread.Sleep pins it. Full Sleep vs Delay and Task vs Thread: Task vs Thread.
Task.Run) — map onlyUse Task.Run for CPU-bound work, not to wrap EF I/O. When not to use it on ASP.NET Core: Task.Run vs await.
Same async/await syntax. async void is only for UI event handlers — never ASP.NET Core actions. UI-only: Task.Yield.
Async is not multithreading. One thread can await SQL, then await HTTP, sequentially.
Concurrent async means starting independent I/O, then awaiting together. Never Task.WhenAll two ToListAsync calls on the same DbContext. Caps and patterns: Task.WhenAll.
Async frees the worker during I/O. Multithreading coordinates CPU work and shared memory. Full map: C# multithreading primer.
| Topic | Winner article |
|---|---|
| Request-path checklist | Async/await in ASP.NET Core |
504 / idle CPU / .Result | Thread pool starvation |
| ConfigureAwait / ValueTask / IAsyncEnumerable | ConfigureAwait · Task vs Thread · IAsyncEnumerable |
| Mistake | Where to fix |
|---|---|
async with no await | This primer (CS4014) |
.Result on request path | Starvation |
WhenAll on one DbContext | WhenAll |
async void controller | ASP.NET checklist |
Pick a track below, tap Try it to self-check, or open a spoke article from the table at the top.
Try it — tap to reveal
Async frees the worker during I/O; sync pins it. Full side-by-side tables: async vs sync.
.Result on a service, fake async, and WhenAll on one DbContext are all wrong. Production checklist: async/await in ASP.NET Core. WhenAll deep dive: Task.WhenAll.
No. Sequential awaits are asynchronous but not parallel. Independent I/O can run together — never two ToListAsync on one DbContext. Caps: Task.WhenAll.
Related: Interview Questions · EF Core
Async and await in C# implement the Task-based Asynchronous Pattern (TAP). The async modifier marks a method that returns Task or Task<T>. The await operator pauses that method until I/O completes and returns control to the caller meanwhile. Use them for SQL, HTTP, and files — not to speed up a single query, but to free threads under load. Language examples on this hub; ASP.NET production checklist: async/await in ASP.NET Core.
async is a modifier on the method signature — it enables await inside and makes the method return a Task. await is an operator used inside an async method on an awaitable call. You need both: async declares the async method; await is where execution yields. They are not interchangeable keywords.
Mark the method async, return Task or Task<T>, and await each I/O call. Example: public async Task<OrderDto?> GetOrderAsync(Guid id, CancellationToken ct) { var order = await _db.Orders.FirstOrDefaultAsync(o => o.Id == id, ct); return Map(order); } — more examples on this hub. Dictionary terms: asynchronous meaning. Request-path rules: async/await in ASP.NET Core.
The caller gets a Task immediately. At await, the runtime yields the thread/worker until the operation completes, then runs the continuation. On ASP.NET Core that means the ThreadPool worker serves other clients during SQL/HTTP waits. Step-by-step on this hub under How async and await works in C#.
An async method in C# is any method (or lambda) marked with async that returns Task, Task<T>, or in rare UI cases void. It must use await on real I/O (or return Task.FromResult without async). API controllers should return async Task<IActionResult>, never async void.
No — async does not shorten SQL, HTTP, or disk time. It frees the ThreadPool worker during the wait so one API can serve more concurrent clients. Async improves throughput, not single-query speed. 504 / idle-CPU failure mode: thread pool starvation.
This hub is the language primer and article map. Open Task vs Thread, Task.WhenAll, thread pool starvation, or the tracks below — each owns that SERP.