*
Previous Threading in C# Asynchronous Programming with async/await in C# Next

Task Parallel Library (TPL) in C#

Task Parallel Library (TPL) in C#

The Task Parallel Library (TPL) is a set of APIs within the System.Threading.Tasks namespace that simplifies adding parallelism and concurrency to C# applications. Introduced in .NET Framework 4.0, it provides a task-based model that is more efficient and scalable than traditional thread management.

Instead of manually creating and managing threads, the TPL uses a thread pool and automatically balances the workload across available processor cores. It manages complexities such as work partitioning, scheduling, load balancing, and exception handling.

Key Components of the TPL

1. Task and Task<TResult>

The Task class represents a single asynchronous operation. The generic Task<TResult> represents a task that returns a result of type TResult.

Example:

using System;
using System.Threading.Tasks;

public class TaskExample
{
public static void Main()
{
// Create and start a task that returns a result
Task taskWithResult = Task.Run(() =>
{
Console.WriteLine("Task is calculating...");
return 10 * 10;
});

    // Wait for the task to complete and get the result
    int result = taskWithResult.Result;
    Console.WriteLine($"Result from task: {result}");
}

} 

2. The Parallel Class

The Parallel class provides static methods for executing loops in parallel, simplifying the process of parallelizing for and foreach loops.

Example: Parallel.ForEach

using System;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ParallelExample
{
public static void Main()
{
var items = new List { 1, 2, 3, 4, 5 };


    // Execute a loop in parallel
    Parallel.ForEach(items, item =>
    {
        Console.WriteLine($"Processing item {item} on thread {Task.CurrentId}");
    });
}

} 
  • Parallel.For: For numeric loops.
  • Parallel.Invoke: Runs multiple Action delegates in parallel.

3. async and await

Introduced in C# 5.0, async and await are built on top of the TPL, making asynchronous programming simpler and more readable. await pauses method execution until a Task completes without blocking the thread, ideal for I/O-bound tasks.

Example: async/await with TPL

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class AsyncExample
{
public static async Task Main()
{
Console.WriteLine("Main thread started.");


    var httpClient = new HttpClient();
    
    // Await the completion of an I/O-bound task
    string html = await httpClient.GetStringAsync("https://example.com");

    Console.WriteLine($"Web page downloaded. HTML length: {html.Length}");
    Console.WriteLine("Main thread finished.");
}

} 

4. Task Coordination

The TPL provides methods to coordinate multiple tasks:

  • Task.WhenAll: Completes when all provided tasks are finished.
  • Task.WhenAny: Completes when any one of the provided tasks finishes.

🧠 What Is TPL?

The Task Parallel Library (TPL) is a set of public types and APIs in the System.Threading and System.Threading.Tasks namespaces that simplify writing multithreaded and parallel code. It abstracts away the complexity of thread management, making it easier to write scalable and efficient applications.

πŸ•’ Version Introduced

πŸ“Œ TPL was introduced in .NET Framework 4.0, released in 2010. It has since become the preferred way to write parallel and asynchronous code in .NET, including .NET Core and .NET 5+.

βš™οΈ Key Features of TPL

  • Task-based programming model (Task, Task<T>)
  • Parallel loops (Parallel.For, Parallel.ForEach)
  • Task composition (Task.WhenAll, Task.WhenAny)
  • Cancellation support (CancellationToken)
  • Exception handling for aggregated exceptions
  • Thread pool management (automatic scaling)

πŸ§ͺ Examples

πŸ”Ή Task Creation

Task task = Task.Run(() => Console.WriteLine("Running in parallel"));

πŸ”Ή Parallel Loop

Parallel.For(0, 5, i => Console.WriteLine($"Iteration {i}"));

πŸ”Ή Task with Return Value

Task<int> task = Task.Run(() => 42);
int result = task.Result; // Blocks until completed

πŸ”Ή Task Composition

Task.WhenAll(
    Task.Run(() => Console.WriteLine("Task 1")),
    Task.Run(() => Console.WriteLine("Task 2"))
).Wait();

πŸ”Ή Cancellation

var cts = new CancellationTokenSource();
Task.Run(() => {
    while (!cts.Token.IsCancellationRequested) {
        Console.WriteLine("Working...");
    }
}, cts.Token);
cts.Cancel(); // Request cancellation

βœ… Best Practices

  • Use async/await with Task for asynchronous workflows.
  • Prefer Task.Run over manually creating threads.
  • Use ConfigureAwait(false) in library code to avoid deadlocks.
  • Avoid blocking calls like .Wait() or .Result in async code.
  • Use CancellationToken for cooperative cancellation.

πŸ“Œ When to Use

  • For CPU-bound operations that benefit from parallelism.
  • To keep UI responsive in desktop or mobile apps.
  • In server-side applications to handle concurrent requests.
  • For data processing, simulations, or batch jobs.

🚫 When Not to Use

  • For I/O-bound operations β€” use async/await instead.
  • When parallelism adds more overhead than performance benefit.
  • In ASP.NET Core controllers β€” they’re already parallelized.
  • For short-lived tasks that don’t justify thread creation.

⚠️ Precautions

  • Avoid over-parallelizing β€” can lead to thread starvation.
  • Handle AggregateException when using Task.Wait() or .Result.
  • Be cautious with shared state β€” use locks or thread-safe collections.
  • Monitor performance β€” parallelism isn’t always faster.

🎯 Advantages

  • βœ… Simplifies parallel and asynchronous programming
  • βœ… Automatically manages thread pooling
  • βœ… Scales with processor cores
  • βœ… Improves performance and responsiveness
  • βœ… Integrates seamlessly with async/await
  • Simplicity: Focus on logic instead of thread management.
  • Efficiency and scalability: Uses thread pooling and multi-core processors effectively.
  • Robust error handling: Exceptions are aggregated in an AggregateException.
  • Cooperative cancellation: Safe task cancellation with CancellationTokenSource.

Limitations and Considerations

  • Overhead: Small, short loops may not benefit due to parallelization overhead.
  • Not for I/O-bound operations: Use async/await instead of Parallel constructs.
  • Complexity: Shared resource management is still required to avoid race conditions.

πŸ“ Conclusion

The Task Parallel Library (TPL) revolutionized how developers write concurrent code in C#. Introduced in .NET Framework 4.0, it provides a high-level, flexible, and efficient model for parallelism. Whether you're building desktop apps, web services, or data pipelines, TPL helps you harness the power of modern multicore processors with minimal effort.

Back to Index
Previous Threading in C# Asynchronous Programming with async/await in C# Next
*
*