Task / Task<T>
`Task` represents an asynchronous operation that does not return a value, while `Task<T>` represents an asynchronous operation that returns a value of type `T`.
Task myTask = SomeAsyncOperation();This static page keeps the syntax and examples indexed for search, while the coding app handles interactive exploration and saved references.
What it does
Overview
`Task` represents an asynchronous operation that does not return a value, while `Task<T>` represents an asynchronous operation that returns a value of type `T`.
`Task` and `Task<TResult>` are fundamental types in C#'s Task Parallel Library (TPL) and the foundation for `async`/`await`. A `Task` object represents a unit of work that can be executed asynchronously, potentially on a separate thread or by leveraging I/O completion ports. It encapsulates the state of an asynchronous operation, including whether it's running, completed successfully, canceled, or faulted. `Task<TResult>` extends `Task` by adding a generic type parameter `TResult`, indicating that the asynchronous operation will eventually produce a result of that type. When an `async` method is called, it immediately returns a `Task` or `Task<TResult>` instance, allowing the caller to continue execution. The actual work of the `async` method proceeds in the background. You can `await` these `Task` objects to pause execution until the operation completes, or use methods like `ContinueWith` for continuation-based programming. Time complexity is not directly applicable to `Task` objects themselves, but rather to the operations they represent. Edge cases include observing exceptions (unhandled exceptions in `Task`s can be problematic if not awaited or handled via `Exception` property), and managing task lifetimes. Best practices involve always `await`ing tasks or handling their exceptions explicitly to prevent silent failures, and understanding the difference between `Task.Wait()` (blocking) and `await` (non-blocking).
Quick reference
Syntax
Task myTask = SomeAsyncOperation();
See it in practice
Examples
Creating and awaiting a non-generic Task
using System.Threading.Tasks;
using System;
public class TaskExample
{
public static async Task DoSomethingAsync()
{
Console.WriteLine("Task started.");
await Task.Delay(1000);
Console.WriteLine("Task finished.");
}
public static async Task Main()
{
Console.WriteLine("Main before task.");
await DoSomethingAsync();
Console.WriteLine("Main after task.");
}
}Main before task. Task started. Task finished. Main after task.
Illustrates a `Task` representing an asynchronous operation that doesn't return a value, and how `await` pauses the caller until it completes.
Creating and awaiting a Task<T> with a result
using System.Threading.Tasks;
using System;
public class TaskTExample
{
public static async Task<string> FetchDataAsync()
{
Console.WriteLine("Fetching data...");
await Task.Delay(1500);
return "Data from server";
}
public static async Task Main()
{
Console.WriteLine("Main requesting data.");
string data = await FetchDataAsync();
Console.WriteLine($"Received: {data}");
}
}Main requesting data. Fetching data... Received: Data from server
Shows `Task<string>` for an operation that returns a string, and how `await` retrieves the result.
Handling exceptions from a Task
using System.Threading.Tasks;
using System;
public class TaskExceptionExample
{
public static Task SimulateErrorAsync()
{
return Task.Run(() => { throw new Exception("Error in background task!"); });
}
public static async Task Main()
{
try
{
await SimulateErrorAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Caught: {ex.Message}");
}
}
}Caught: Error in background task!
Demonstrates that exceptions thrown within a `Task` are propagated when the `Task` is awaited, allowing for standard `try-catch` handling.
Debug faster
Common Errors
Unobserved Task Exception
Cause: An exception occurs in a `Task` that is not awaited and its exception is never retrieved (e.g., by accessing `.Exception` property). In .NET Core and .NET 5+, unobserved task exceptions no longer crash the process by default.
Fix: Always `await` tasks or explicitly handle their exceptions (e.g., by accessing `task.Exception` and marking it as observed) to prevent silent failures or unexpected behavior.
public Task DoWorkAndFail() { return Task.Run(() => { throw new Exception("Oops!"); }); }
// In Main, if you just call:
// DoWorkAndFail(); // The exception might go unobservedRuntime support
Compatibility
Source: Microsoft Learn
Common questions
Frequently Asked Questions
`Task` represents an asynchronous operation that does not return a value, while `Task<T>` represents an asynchronous operation that returns a value of type `T`.
Unobserved Task Exception: Always `await` tasks or explicitly handle their exceptions (e.g., by accessing `task.Exception` and marking it as observed) to prevent silent failures or unexpected behavior.