C#AsyncIntermediate

Task.Run()

Schedules a CPU-bound operation to run on a thread pool thread and returns a `Task` or `Task<TResult>` representing that operation.

Review the syntaxStudy the examplesOpen the coding app
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

functionAction or Func<TResult> or Func<Task> or Func<Task<TResult>> · The delegate to execute asynchronously.

See it in practice

Examples

1

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}");
    }
}
Output:
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.

2

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}");
    }
}
Output:
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.

3

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}");
    }
}
Output:
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

1

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); }); } // Inefficient

Runtime support

Compatibility

.NETN/A.NET Framework 4.5+, .NET Core 1.0+

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()`.