Task Parallel Library in C#
Last Updated :
04 Mar, 2025
In C#, Task Parallel Library (TPL) is a collection of APIs that provides more control over parallel and asynchronous programming. It is present in the System.Threading.Tasks namespace. TPL simplifies multithreading by managing thread scheduling and execution efficiently. It includes features like data parallelism, task scheduling, and supportive cancellation. TPL provides a higher level of abstraction over traditional threading mechanisms, making it easier to write, read, and maintain parallel code.
- TPL reduces CPU overheating in long-running tasks.
- It makes Thread Management easier and doesn't worry about race conditions.
- Provide an efficient way to cancel a task co-operatively through CancellationToken.
- TPL is used for its better CPU utilization, enhancing performance, and is a better alternative to the traditional Thread class.
Example: This program creates Tasks to print numbers using the Task Parallel Library.
C#
// Implementation of Multithreading
// in C# using Task Class
using System;
using System.Threading.Tasks;
class Geeks
{
static void Main()
{
// Creating and starting two
// tasks to run concurrently
Task task1 = Task.Run(() => PrintNumbers());
Task task2 = Task.Run(() => PrintNumbers());
// Waiting for both tasks to complete
// before exiting the program
Task.WhenAll(task1, task2).Wait();
}
static void PrintNumbers()
{
// Printing numbers from 0 to 2 in each task
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i);
}
}
}
Task Class
Task class used for more complex or parallel tasks is an important part of the TPL. The Task class allows us to create tasks that can run asynchronously, improving both performance and code readability. It also simplifies task management by handling thread pooling and synchronization. It reduces the task of managing threads manually like the traditional way using Thread Class.
Example: This program demonstrates how to create and run a task using the Task class.
C#
// Implementation of Multithreading in C# using
// Task Class to run multiple tasks concurrently
using System;
using System.Threading.Tasks;
class Geeks
{
static void Main()
{
// Running two tasks concurrently
Task task1 = Task.Run(() => PrintNumbers());
Task task2 = Task.Run(() => ReverseNumbers());
// Wait for both tasks to complete
Task.WhenAll(task1, task2).Wait();
}
static void PrintNumbers()
{
// Printing numbers from 0 to 2
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i);
}
}
static void ReverseNumbers()
{
// Printing numbers from 2 to 0
for (int i = 2; i >= 0; i--)
{
Console.WriteLine(i);
}
}
}
Explanation: In the above example we create two tasks one is for printing the numbers from the start and one for printing the numbers in the reverse order and using the method Task.Run() to start the task and pass the method in the argument using the anonymous function.
Task Cancellation
Task cancellation is an important part of the Task class. Task class provides an effective way to cancel a task co-operative using the CancellationToken from the CancellationTokenSource class. Thread.Abort() is not recommended in modern C# as it is unsafe. Instead, Task cancellation is handled properly using CancellationToken without forcibly terminating a thread which will throw an exception which will interrupt the flow of the program.
Example: This program is used to demonstrate how to cancel a task using the CancellationToken.
C#
// Implementation of Multithreading in C# using
// Parallel.ForEach with CancellationToken support
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
List<string> data = new List<string> { "Hello", "Geek", "How", "Are", "You" };
// Create a CancellationTokenSource
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
// Create a task that uses the CancellationToken
Task.Run(() =>
{
try
{
Console.WriteLine("Task started.");
Parallel.ForEach(data, new ParallelOptions { CancellationToken = token }, item =>
{
// Check for cancellation
token.ThrowIfCancellationRequested();
Console.WriteLine($"Data [{item}] on thread: {Thread.CurrentThread.ManagedThreadId}");
});
Console.WriteLine("Task completed.");
}
catch (OperationCanceledException)
{
Console.WriteLine("Task was canceled.");
}
}, token);
Task.Delay(200).Wait();
// Cancel the task
cts.Cancel();
// Dispose the CancellationTokenSource
cts.Dispose();
Console.WriteLine("Main method completed");
}
}
OutputTask started.
Data [How] on thread: 7
Data [Hello] on thread: 4
Data [Are] on thread: 8
Data [Geek] on thread: 6
Data [You] on thread: 7
Task completed.
Main method completed
Parallel Class
Parallel class is a part of TPL. and present in the System.Threading.Tasks namespace. It provides various looping methods to achieve parallelism and It is an easier way to iterate through the parallel programs. It has powerful abstract methods which are used to perform different operations on parallel tasks. These are the important iterating methods that are mainly used in the parallel class.
Parallel.For()
This method is used to execute the loops in parallel. It is an efficient way to iterate through the tasks which work independently. And we can use this loop to iterate concurrently which enhances the computational speed and reduce the overhead. It divides the loop iterations into separate threads and runs concurrently.
Syntax:
Parallel.For(int fromInclusive, int toExclusive, Action<int> body)
- fromInclusive: The starting index of the loop.
- toExclusive: The exclusive end index of the loop (one past the last index).
- body: We need to pass the Action<int> delegate which is the action to be performed.
It takes three parameters: the start index, the end index, and a delegate that represents the body of the loop.
Example:
C#
// Implementation of Multithreading in C#
// using Parallel.ForEach for concurrent processing
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
List<string> data = new List<string> { "Hello", "Geek", "How", "Are", "You" };
// Process each element in parallel
Parallel.ForEach(data, ele =>
{
Console.WriteLine($"Data => {ele} on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
});
}
}
OutputData => Hello on thread:- 1
Data => Geek on thread:- 4
Data => How on thread:- 5
Data => Are on thread:- 6
Data => You on thread:- 7
Explanation: The Parallel.ForEach() loop separates the data present in the list in small chunks and runs it on a different thread as shown in the output note that if we run this code it will give the output differently each time.
Parallel.ForEach()
This method is also used to iterate parallel loops and the using this loop we can easily iterate over the collections in C# like list, array set or any other collection. The main difference is that it works directly on the collection and we don't need to specify the start and end index instead we just simply pass the collection in the argument directly.
Syntax:
ForEach<TSource>(IEnumerable<TSource> source, Action<TSource> body)
- collection: We can pass any collection like array, list or set which we want to iterate.
- body: An Action<T> delegate that defines the work to be done for each item in the collection.
Example:
C#
// Implementation of Multithreading in C# using
// Parallel.ForEach for concurrent data processing
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
List<string> data = new List<string> { "Hello", "Geek", "How", "Are", "You" };
// Process each element in parallel
Parallel.ForEach(data, ele =>
{
Console.WriteLine($"Data => [{ele}] on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
});
}
}
OutputData => [Hello] on thread:- 1
Data => [Geek] on thread:- 1
Data => [How] on thread:- 1
Data => [Are] on thread:- 1
Data => [You] on thread:- 1
Explanation: In the above code we use the Parallel.ForEach() method executes the data collection on the separate thread as shown in the output and note that each time we run the program the output will be different each time.
Note: the thread assignments may change each time.
Parallel.Invoke()
This method is used to run multiple methods or any action concurrently. And doesn't require to creation of a loop. We can use this method when we have multiple actions to perform and they are not dependent on each other and can be executed parallelly. It runs the actions at the same time which enhances the performance.
Syntax:
Parallel.Invoke(Action[] actions);
actions: An array of Action delegates representing the independent tasks that need to be executed in parallel.
Example:
C#
// Implementation of Multithreading in C# using
// Parallel.Invoke for concurrent execution of multiple actions
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
List<string> data = new List<string> { "Hello", "Geek", "How", "Are", "You" };
// Execute multiple tasks in parallel
Parallel.Invoke(
() => Console.WriteLine($"Data => [{data[0]}] on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}"),
() => Console.WriteLine($"Data => [{data[1]}] on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}"),
() => Console.WriteLine($"Data => [{data[2]}] on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}"),
() => Console.WriteLine($"Data => [{data[3]}] on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}"),
() => Console.WriteLine($"Data => [{data[4]}] on thread:- {System.Threading.Thread.CurrentThread.ManagedThreadId}")
);
}
}
OutputData => [Hello] on thread:- 1
Data => [Geek] on thread:- 6
Data => [How] on thread:- 5
Data => [Are] on thread:- 5
Data => [You] on thread:- 4
Explanation: In the above code we use the Invoke() method from the parallel class and we don't need to create a loop we just write the method in the lambda function and it executes parallelly.
Error Handling
TPL provides a better way to handle the error using AggregateException. When we are using the task class and it not working according and throws an error we need to handle it so the flow of the program will execute accordingly. Using the AggregateException we can handle different kinds of exceptions.
Example: Handling an error in TPL using the AggregateException in Task class.
C#
// Implementation of Exception Handling in C#
// using Task and AggregateException
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
List<string> data = new List<string> { "Hello", "Geek", "How", "Are", "You" };
// Create a task that may throw exceptions
Task task = Task.Run(() =>
{
if (data.Contains("How"))
{
throw new InvalidOperationException("Error: data list contains the word \"How\"");
}
});
try
{
// Wait for the task to complete
task.Wait();
}
catch (AggregateException ex)
{
// Handle the exception
Console.WriteLine($"Handled exception: {ex.Message}");
}
}
}
OutputHandled exception: One or more errors occurred. (Error: data list contains the word "How")
Explanation: In the above example we create a custom error if the list contains a questionable word like "How" so it will throw an error and we handled this error using the AggeregateException.
Similar Reads
How to Install NPOI Library on c#?
NPOI is an open-source .NET library that allows you to read and write Microsoft Office file formats. NPOI is built on top of the Apache POI project, a Java library for working with Office files. NPOI provides a similar set of features as the Apache POI library but is explicitly designed for use with
2 min read
What is Reflection in C#?
Reflection is the process of describing the metadata of types, methods and fields in a code. The namespace System.Reflection enables you to obtain data about the loaded assemblies, the elements within them like classes, methods and value types. Some of the commonly used classes of System.Reflection
4 min read
C# | Inheritance in interfaces
C# allows the user to inherit one interface into another interface. When a class implements the inherited interface then it must provide the implementation of all the members that are defined within the interface inheritance chain.Important Points: If a class implements an interface, then it is nece
3 min read
Partial Methods in C#
C# contains a special method is known as a partial method, which contains declaration part in one partial class and definition part in another partial class or may contain both declaration and definition in the same partial class. Basically, partial methods exist in the partial class, or in the stru
2 min read
Garbage Collection in C# | .NET Framework
Garbage collection is a memory management technique used in the .NET Framework and many other programming languages. In C#, the garbage collector is responsible for managing memory and automatically freeing up memory that the application is no longer using.The garbage collector periodically scans th
8 min read
How to Install Nuget Package in C#?
In this tutorial, we will be seeing how to install NuGet packages in C#. NuGet is the official package-manager for .NET. Packages are basically compiled libraries with some descriptive metadata. NuGet is an important tool for any modern development platform through which developers can create, share
3 min read
C# Task Class
The Task class is part of the Task Parallel Library (TPL) in System.Threading.Tasks. Introduced in .NET Framework 4.0, it provides a higher-level abstraction for asynchronous programming and parallelism. It allows operations to run in the background or in parallel with other tasks without blocking t
10 min read
.NET Framework Class Library (FCL)
The Framework Class Library or FCL provides the system functionality in the .NET Framework as it has various classes, data types, interfaces, etc. to perform multiple functions and build different types of applications such as desktop applications, web applications, mobile applications, etc. The Fra
3 min read
How to Install npgsql in c#?
Npgsql is a .NET data provider for PostgreSQL, a popular open-source database management system. It allows applications written in .NET languages (such as C# or VB.NET) to connect to and interact with a PostgreSQL database. Npgsql is an open-source .NET data provider for PostgreSQL, a popular open-s
2 min read
Out Parameter With Examples in C#
The out is a keyword in C# which is used for the passing the arguments to methods as a reference type. It is generally used when a method returns multiple values. Important Points: It is similar to ref keyword. But the main difference between ref and out keyword is that ref needs that the variable m
5 min read