Syntax
Task<T> task = SomeAsyncMethod();Examples
Creating and Running a Task
Starting work on a separate task and awaiting its completion.
Task<int> CalculateAsync()
{
return Task.Run(() =>
{
Thread.Sleep(500); // simulate CPU-bound work
return 6 * 7;
});
}
int result = await CalculateAsync();
Console.WriteLine(result); // 42Task Status and Properties
Inspecting a task's state without necessarily awaiting it immediately.
Task<int> task = Task.Run(() =>
{
Thread.Sleep(300);
return 100;
});
Console.WriteLine(task.IsCompleted); // false, probably still running
int result = await task;
Console.WriteLine(task.IsCompleted); // true
Console.WriteLine(result); // 100Task.CompletedTask and Task.FromResult
Returning an already-completed task, useful for satisfying an async interface without real async work.
Task LogAsync(string message)
{
Console.WriteLine(message);
return Task.CompletedTask; // no real async work needed, but interface requires Task
}
Task<int> GetCachedValueAsync(int cached)
{
return Task.FromResult(cached); // wraps an already-known value in a Task
}
await LogAsync("Started");
int value = await GetCachedValueAsync(99);
Console.WriteLine(value);Best practices
- Use Task.Run() specifically for offloading CPU-bound work to a background thread - it is not needed for naturally async I/O operations like HttpClient calls, which are already non-blocking
- Prefer awaiting a Task directly over checking .IsCompleted in a polling loop - awaiting is more efficient and far simpler to reason about
- Use Task.FromResult() or Task.CompletedTask when implementing an async interface method that has no real asynchronous work to do
- Avoid using .Result or .Wait() to synchronously block on a Task - always prefer await, which does not risk deadlocks or block the calling thread
At a glance
- Purpose
- Applications on the .NET platform
- File extension
- .cs
- Runs in
- .NET runtime
- Usually used with
- .NET SDK and libraries
Specifications & further reading
Related C# documentation
async and await
The async and await keywords let you write asynchronous code that reads almost like ordinary sequential code. Marking a method async allows it to use await, which pauses execution at that point until the awaited operation completes, without blocking the calling thread - freeing it up to do other work in the meantime. This is essential for keeping applications responsive during I/O-bound work like network calls, file access, or database queries.Task.WhenAll & Task.WhenAny
Task.WhenAll() lets you run multiple independent asynchronous operations concurrently and await all of them together, completing once every task finishes - much faster than awaiting them one at a time. Task.WhenAny() completes as soon as the first of several tasks finishes, useful for timeout patterns or taking whichever result arrives first.CancellationToken
CancellationToken provides a standard, cooperative way to signal that an asynchronous operation should stop before it completes naturally. A CancellationTokenSource creates the token and controls when cancellation is requested; the token itself is passed into async methods, which check it periodically (or pass it to another cancellable operation) and can throw an OperationCanceledException to unwind cleanly.Async Pitfalls: void vs Task, ConfigureAwait
A few recurring mistakes trip up many C# developers new to async: using async void instead of async Task (which makes exceptions impossible to catch normally), and blocking on async code with .Result or .Wait() (which can cause a deadlock in contexts with a synchronization context, like older ASP.NET or WPF apps). Understanding these pitfalls up front avoids some of the most common async-related bugs.
The async and await keywords let you write asynchronous code that reads almost like ordinary sequential code. Marking a method async allows it to use await, which pauses execution at that point until the awaited operation completes, without blocking the calling thread - freeing it up to do other work in the meantime. This is essential for keeping applications responsive during I/O-bound work like network calls, file access, or database queries.Task.WhenAll & Task.WhenAny
Task.WhenAll() lets you run multiple independent asynchronous operations concurrently and await all of them together, completing once every task finishes - much faster than awaiting them one at a time. Task.WhenAny() completes as soon as the first of several tasks finishes, useful for timeout patterns or taking whichever result arrives first.CancellationToken
CancellationToken provides a standard, cooperative way to signal that an asynchronous operation should stop before it completes naturally. A CancellationTokenSource creates the token and controls when cancellation is requested; the token itself is passed into async methods, which check it periodically (or pass it to another cancellable operation) and can throw an OperationCanceledException to unwind cleanly.Async Pitfalls: void vs Task, ConfigureAwait
A few recurring mistakes trip up many C# developers new to async: using async void instead of async Task (which makes exceptions impossible to catch normally), and blocking on async code with .Result or .Wait() (which can cause a deadlock in contexts with a synchronization context, like older ASP.NET or WPF apps). Understanding these pitfalls up front avoids some of the most common async-related bugs.