Parallel Task in .Net 4.0

Today I will be talking about a new feature of Parallel Programming that was added to .Net 4.0. This article is intended for those familiar with Threads in C#.
 
Considering an example, wherein if one person wants to dig the ground in a 15 mts area then it will take a long time to dig it as required. But if the same work is done by more than 1 person in parallel then the task can be completed faster.
 
faster
 
When I remember having work done single-handed, the following code snippet will answer your question.
  1. Stopwatch watch = new Stopwatch();  
  2.  /*Start Timer*/  
  3.  watch.Start();  
  4.   
  5. /*Task to be performed*/  
  6. for (int index = 0; index < 15; index++)  
  7. {  
  8.       Console.WriteLine("Digging completed for " + index + "mts. area");  
  9.      Thread.Sleep(1000);  
  10. }  
  11. /*Stop Timer*/  
  12. watch.Stop();  
  13. Console.WriteLine("Time required single handed: " + watch.Elapsed.Seconds); 
Output
 
Output
 
Now how to add multiple people working on the same task in parallel?
 
task
 
.Net 4.0 added a new feature of Parallel Programming. This Parallel Programming can be done using Task Parallel Library (TPL). This library is available from the namespace System.Threading.Tasks.
 
The Task Parallel Library (TPL) is the base of the Task-based programming. It consists of:
  • Task class is used to do the unit of work you will code for instead of the previous thread model.
  • Parallel class is a static class that exposes a task-based version of some parallel-nature problems. 
If the same work is to be done with more than 1 worker then what do I need to write?
  1. Stopwatch watch = new Stopwatch();  
  2. watch.Start();  
  3. System.Threading.Tasks.Parallel.For(0, 15, index =>  
  4. {  
  5.     Console.WriteLine("Digging completed for " + index + "mts. area ");  
  6.     Thread.Sleep(1000);                   
  7. }  
  8. );  
  9. watch.Stop();  
  10. Console.WriteLine("Time required time for Parallel digging: " + watch.Elapsed.Seconds); 
Output
 
Result
 
As you can see the difference in timing required by a worker to complete the task single-handedly and by more than 1 respectively. This gives a huge improvement in execution timing when Parallel. For is used.
 
Another alternative is by using Parallel. ForEach that is similar to a foreach loop.
 
Parallel.Invoke
 
Parallel.Invoke
 
Suppose concurrently I want to do many tasks, like digging, cleaning, and so on. So this can be done using the Parallel.Invoke static method. This method will allow me to add various operations and execute them concurrently in parallel.
  1. private void OtherTask()  
  2. {  
  3.     //Some task  
  4. }  
  5.   
  6. private void Digging()  
  7. {  
  8.    //Some task  
  9. }  
  10.   
  11. private void CleanIt()  
  12. {  
  13.     //Some task  
  14. }  
  15.   
  16. public void CallAllTask()  
  17. {  
  18.     Parallel.Invoke(  
  19.       new Action(OtherTask)  
  20.       , new Action(Digging)  
  21.       , new Action(CleanIt));  
The code snippet above will execute all of the list of operations in parallel.
 
ParallelLoopState
 
 
Suppose I want to stop my work after digging at a 10 mts. area. If only one worker was doing this task then it would have been easy. But since many are working in these tasks and each worker is unaware of what the other is doing, I need someone that can interact with each worker and know what is the state of each person's work. In other words before stopping the Parallel Task, I need to maintain a state of the Parallel Tasks executing. This task is handled by the ParallelLoopState class.
 
ParallelLoopState: Enables iterations of Parallel loops to interact with other iterations.
 
There are 2 methods Break () and Stop () to end the task.
 
The differences between the Break and Stop methods are
  • Break ensures that all earlier iterations that started in the loop are executed before exiting the loop.
  • Stop makes no such guarantees; it says that this loop is done and should exit as soon as possible.
  1. Parallel.For(0, 15, (int index, ParallelLoopState loopState) =>  
  2. {  
  3.     if (index == 10)  
  4.     {  
  5.         loopState.Break();  
  6.         //loopState.Stop();  
  7.     }  
  8.     Console.WriteLine("Digging for " + index + "mts. area ");  
  9.     Thread.Sleep(1000);                   
  10. }); 
Output
 
Show Output
 
Using Stop (), as you can see only 11 threads are executed and the task came to a halt.
 
threads
 
Using Break, as you can see one extra loop was executed. This is because as the parallel threads were executing, so it completed the ongoing thread and then stopped.
 
PLINQ
 
LINQ is used for querying through the collection, similarly, PLINQ can be used to query the collection executed with multiple threads. The AsParallel extension method to the collection allows you to query the collection using multiple threads.
  1. bool[] result1 = arr.AsParallel().Select(x => CheckForEven(x)).ToArray(); 
ContinueWith
 
As we know, Task is executed in a different thread. So it is executed asynchronously. And there may be the case that once my task is done, I want to do some other task after completion of the first. This can be done using the ContinueWith extension method.
 
ContinueWtih extension method
  1. Task t2 = null;  
  2. Task t = Task.Factory.StartNew(() =>  
  3. {  
  4.     Console.WriteLine("Digging is in progress");  
  5. });  
  6.   
  7. Console.WriteLine("");  
  8.               
  9. t2 = t.ContinueWith((a) => {  
  10. Console.WriteLine("Clean the area");  
  11. for (int index = 1; index <= 5; index++)  
  12. {  
  13.    Console.WriteLine("Cleaning...." + index);  
  14. }  
  15.  Console.WriteLine("Cleaning done");  
  16.   });  
  17. Task.WaitAll(t, t2);// To ensure both tasks are completed  
  18. Console.Read(); 
In the code snippet above, I am creating a task using the TaskFactory class. Since this task is executed asynchronously, it will continue its execution in a separate Thread. Once this execution is completed, create another Task linked to the first task using the ContinueWith() method.
 
Output
 
ContinueWith method
 

Conclusion

 
Here I conclude this article, saying Parallel programming makes our work easier and faster. I hope you like this article. Please share your comments, whether its good or bad. Sharing is valuable no matter what :)
 
References