Parallel LINQ (PLINQ) in C#
Introduction
Parallel LINQ (PLINQ) is a parallel implementation of LINQ to Objects. It is designed to make it easier to write parallel code in C#. PLINQ can improve the performance of data processing tasks by utilizing multiple processors. It allows you to run LINQ queries in parallel, leveraging the power of multiple cores in modern processors.
Getting Started with PLINQ
To use PLINQ, you need to include the System.Linq
namespace in your project. PLINQ queries are created by calling the AsParallel
method on an enumerable collection, which converts the collection into a parallel query.
Example of a basic PLINQ query:
using System; using System.Linq; class Program { static void Main() { int[] numbers = Enumerable.Range(1, 10).ToArray(); var parallelQuery = numbers.AsParallel().Where(n => n % 2 == 0); foreach (var num in parallelQuery) { Console.WriteLine(num); } } }
Controlling Parallelism
PLINQ provides several ways to control the degree of parallelism. You can specify the maximum degree of parallelism using the WithDegreeOfParallelism
method. This method limits the number of concurrent tasks that can be used to process the query.
Example of controlling parallelism:
using System; using System.Linq; class Program { static void Main() { int[] numbers = Enumerable.Range(1, 20).ToArray(); var parallelQuery = numbers.AsParallel() .WithDegreeOfParallelism(4) .Where(n => n % 2 == 0); foreach (var num in parallelQuery) { Console.WriteLine(num); } } }
Handling Exceptions in PLINQ
Exception handling in PLINQ is different from traditional LINQ. Since PLINQ runs queries in parallel, multiple exceptions can occur simultaneously. PLINQ wraps these exceptions in an AggregateException
, which you can handle accordingly.
Example of handling exceptions in PLINQ:
using System; using System.Linq; class Program { static void Main() { int[] numbers = { 1, 2, 3, 0, 5, 6 }; try { var parallelQuery = numbers.AsParallel().Select(n => 10 / n).ToArray(); } catch (AggregateException ex) { foreach (var innerEx in ex.InnerExceptions) { Console.WriteLine(innerEx.Message); } } } }
Order Preservation
By default, PLINQ does not guarantee the order of elements in the output sequence. If order is important, you can use the AsOrdered
method to preserve the order of elements.
Example of preserving order in PLINQ:
using System; using System.Linq; class Program { static void Main() { int[] numbers = Enumerable.Range(1, 10).ToArray(); var parallelQuery = numbers.AsParallel().AsOrdered().Where(n => n % 2 == 0); foreach (var num in parallelQuery) { Console.WriteLine(num); } } }
Combining PLINQ with Other LINQ Operators
PLINQ can be combined with other LINQ operators to create more complex queries. You can switch between parallel and sequential execution within the same query.
Example of combining PLINQ with other LINQ operators:
using System; using System.Linq; class Program { static void Main() { int[] numbers = Enumerable.Range(1, 20).ToArray(); var query = numbers.AsParallel() .Where(n => n % 2 == 0) .AsSequential() .Select(n => n * n); foreach (var num in query) { Console.WriteLine(num); } } }
Conclusion
PLINQ is a powerful tool for parallelizing data processing tasks in C#. It allows you to leverage multiple processors easily and efficiently. By understanding how to use PLINQ, control parallelism, handle exceptions, and preserve order, you can write more performant and responsive applications.