Using PLINQ (Parallel Language In Query) in .NET 4.0

Posted on 3 830 views

Parallel LINQ (PLINQ) is a parallel implementation of LINQ to Objects. It is located in System.Threading.Tasks.Parallel.

In many scenarios, PLINQ can significantly increase the speed of LINQ to Objects queries by using all available cores on the host computer more efficiently.

I bring you my example, where I tested the speed of PLINQ, and the increase of speed was enormous!

PLINQ vs. ForEach loop comparison

A picture is worth a thousand words!

PLINQ - code bellow

PLINQ

ForEach loop - just a normal loop

ForEach loop


PLINQ get the job done in 02.00 seconds(!), while ForEach loop processed images for 03.25 seconds.

Use Parallel Language Integrated Query (PLINQ) to take advantage of multi-processor computers and the newer wave of multi-core processors.

PLINQ sample code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Drawing;
using System.Threading;
using System.Threading.Tasks;

namespace MB.ParallelLanguageInQuery
{
    class Program
    {
        static void Main(string[] args)
        {
            // ******************************************************************************************
            // For demonstration purpose, I will use images located in Windows 7 default picture folder
            // NOTE - I added some more images so that there is more "job" to do!
            // ******************************************************************************************

            // Get the names of all JPG files
            string[] files = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg");

            // We create new subfolder called "Modified", where we will store modified images
            string subDirectory_Modified = @"C:\Users\Public\Pictures\Sample Pictures\Modified";
            System.IO.Directory.CreateDirectory(subDirectory_Modified);

            // We will use Stopwatch class to determine how long it takes to perform the procedure
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();

            // ------------------------------------------------------------------------------------------
            // PLINQ code - for each file do something...
            // ------------------------------------------------------------------------------------------
            Parallel.ForEach(files, currentFile =>
            {
                string filename = System.IO.Path.GetFileName(currentFile);
                System.Drawing.Image image = System.Drawing.Image.FromFile(currentFile);
                System.Drawing.Graphics graphic = Graphics.FromImage(image);

                // ------------------------------------------------------------------------------------------
                // NOTE - the more complex work you do here, the difference between PLINQ and 
                // sequential foreach loop will be greater
                // ------------------------------------------------------------------------------------------
                graphic.DrawString(filename, new Font("Arial", 15), new SolidBrush(Color.White), new PointF(50, 50));
                graphic.DrawImage(image, 0, 0, 1000, 1000);
                graphic.RotateTransform(180);
                image.Save(System.IO.Path.Combine(subDirectory_Modified, filename));
                // ------------------------------------------------------------------------------------------

                Console.WriteLine("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId);
            });

            stopwatch.Stop();

            Console.WriteLine("\nProcessing complete in {0} seconds. Press any key to exit.", stopwatch.Elapsed);
            Console.ReadKey();
        }
    }
}