Task.Run()
Schedules a CPU-bound operation to run on a thread pool thread and returns a `Task` or `Task<TResult>` representing that operation.
Task Task.Run(Action action)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
Schedules a CPU-bound operation to run on a thread pool thread and returns a `Task` or `Task<TResult>` representing that operation.
`Task.Run()` is a utility method in C# primarily used to offload CPU-bound work from the current thread (often the UI thread or a request-handling thread in a web server) to a thread pool thread. This is crucial for maintaining application responsiveness and scalability. Unlike I/O-bound operations which benefit from `async`/`await` without necessarily using a separate thread for the waiting period, CPU-bound operations genuinely require CPU time. `Task.Run()` effectively wraps a synchronous method or lambda expression in a `Task` and executes it on a background thread. It returns a `Task` (or `Task<TResult>`) that you can then `await` to get the result or wait for completion. The time complexity of `Task.Run()` itself is minimal (scheduling the task), but the complexity of the operation *inside* `Task.Run()` will dictate the overall performance. Edge cases include overusing `Task.Run()` for trivial operations (context switching overhead can negate benefits), or using it for I/O-bound operations (where `async`/`await` with proper asynchronous APIs is more efficient). Best practices involve using `Task.Run()` for genuinely CPU-intensive, blocking operations that would otherwise block the calling thread, ensuring that the work inside `Task.Run()` is truly independent and doesn't require the original thread's synchronization context.
Quick reference
Syntax
Task Task.Run(Action action)
Inputs
Parameters
See it in practice
Examples
Running a CPU-bound operation
using System.Threading.Tasks;
using System;
public class TaskRunExample
{
public static int CalculateFactorial(int n)
{
int result = 1;
for (int i = 1; i <= n; i++) result *= i;
return result;
}
public static async Task Main()
{
Console.WriteLine("Starting CPU-bound calculation...");
Task<int> factorialTask = Task.Run(() => CalculateFactorial(10));
Console.WriteLine("Main thread is free to do other work.");
int result = await factorialTask;
Console.WriteLine($"Factorial of 10 is: {result}");
}
}Starting CPU-bound calculation... Main thread is free to do other work. Factorial of 10 is: 3628800
Offloads a synchronous, CPU-intensive factorial calculation to a thread pool thread, keeping the main thread responsive.
Running a function with a result
using System.Threading.Tasks;
using System;
public class TaskRunResultExample
{
public static async Task Main()
{
Console.WriteLine("Starting data processing...");
Task<string> processTask = Task.Run(() =>
{
Task.Delay(1000).Wait(); // Simulate blocking work
return "Processed Data";
});
Console.WriteLine("Main thread waiting for result...");
string data = await processTask;
Console.WriteLine($"Received: {data}");
}
}Starting data processing... Main thread waiting for result... Received: Processed Data
Demonstrates `Task.Run` with a `Func<TResult>` to get a value back from the background operation.
Chaining with async/await inside Task.Run
using System.Threading.Tasks;
using System;
public class TaskRunAsyncExample
{
public static async Task Main()
{
Console.WriteLine("Starting complex operation...");
Task<string> complexTask = Task.Run(async () =>
{
Console.WriteLine(" Inner task started on thread pool.");
await Task.Delay(500); // I/O-bound part
Console.WriteLine(" Inner task resumed.");
return "Complex Result";
});
Console.WriteLine("Main thread waiting for complex result...");
string result = await complexTask;
Console.WriteLine($"Final result: {result}");
}
}Starting complex operation... Main thread waiting for complex result... Inner task started on thread pool. Inner task resumed. Final result: Complex Result
Shows `Task.Run` wrapping an `async` lambda, allowing both CPU-bound setup and I/O-bound waits within the background task.
Debug faster
Common Errors
Misuse for I/O-bound operations
Cause: Using `Task.Run()` to wrap an already asynchronous (I/O-bound) method, which unnecessarily consumes a thread pool thread while waiting for an I/O operation to complete.
Fix: For I/O-bound operations (e.g., network calls, file access), prefer to use the `async` versions of the APIs directly (e.g., `HttpClient.GetAsync`, `Stream.ReadAsync`) and `await` them without `Task.Run()`.
public async Task<string> FetchUrl(string url) { return await Task.Run(async () => { using var client = new HttpClient(); return await client.GetStringAsync(url); }); } // InefficientRuntime support
Compatibility
Source: Microsoft Learn
Common questions
Frequently Asked Questions
Schedules a CPU-bound operation to run on a thread pool thread and returns a `Task` or `Task<TResult>` representing that operation.
function: The delegate to execute asynchronously.
Misuse for I/O-bound operations: For I/O-bound operations (e.g., network calls, file access), prefer to use the `async` versions of the APIs directly (e.g., `HttpClient.GetAsync`, `Stream.ReadAsync`) and `await` them without `Task.Run()`.