Tuesday, 9 July 2013

C# Running Multiple threads at a same time and wait for all of them to Finish

Some times we have a scenario to do the task in multiple threads and execute the threads at a same time. Execute the threads at a same time is easy but wait for all threads to finish and then continue the next process is little bit tedious. This can be done in various ways.

Now we can see some of them Samples how we can make wait for finish the all tasks.

ThreadPool

What is Thread Pool ?
       ThreadPool is basically a collection of Threads ,Which will run the threads in Asynchronous process.This  manages the execution of threads.

Things to be Remember when using ThreadPool 

1. We are giving a method reference to the ThreadPool for execution.
2. The ThreadPool waits for an Ideal thread.
3. When Ideal threads found Thread pool uses it to execute our method.
4. Thread executed and terminated
5. ThreadPool returns the thread and make it availble for other threads to process.


        var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        CountdownEvent countdown = new CountdownEvent(items.Length))
        
            foreach (var item in items)
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    Thread.SpinWait(3000);
                    Console.WriteLine("Thread Done!");
                    countdown.Signal();
                });
            }
            countdown.Wait();
        
        Console.WriteLine("Job Done!");

async and await (.Net 4.5)

       using async and await you can avoid the performance bottleneck and improve the performance of the Application. Traditional way of call a async program little bit tedious, But in 4.5 we have Async and Await make this option easy for us.The aync and await keyword are the heart of asynchronous programming.

To do the Async Program Following things should be remember ,

1. async modifier should be included in method signature.
2. The name of the async method should end with "Async" suffix
3. Return type must be void,Task, Task no return 
4. On call the Task object after the await makes the thread to wait for finish the Task.
static void Main(string[] args) { Task<string> runItTask = Run(); Console.WriteLine("End of Main"); Console.ReadLine(); } static async Task<string> Run() { Task<string> t = new Task<string> ( () => { Thread.Sleep(5000); Console.WriteLine("Ended the task"); return "Rajesh"; } ); // start the task t.Start(); string result = await t; Console.WriteLine("After await, result = '" + result + "'"); return result; } 
 
 























Output :  
   Ended the task 
   After await, result = Rajesh
   End of Main 


  CountdownEvent     
           CountdownEvent is the class which holds the count integer of threads and make count all the threads signalled, it make program hold to finish all threads on call a method cntevent.Wait();




Output :




Manual Reset Event 

      In the below code we can see the multi threading 10 threads are invoked , ManualResetEvent will make a wait for the program to hold up the signal got received or Set. In the Below code We are signalling the ManualResetEvent at the Last thread had finished there execution.


        resetEvent.WaitOne();
The above code will wait for signaling from the Event to execute the next line.

How it is knew that last Thread is finished the task. Another static class Interlocked.Decrement ,which will  decrement the variable value at the stage of each task has to be finish. Variable value is decrement with the Ref so the Change must be reflected in all threads. Interlocked.Decrement make a lock on variable and  hold the other threads to wait to access the variable to change .

When the variable reaches 0 that indicates that all threads are finished there Task. then we can signal the ManualResetEvent.Set(),

        int num = 10;        
        int process = 10
        ManualResetEvent resetEvent = new ManualResetEvent(false);
for (int i = 0; i < num; i++) { new Thread(delegate() { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); if (Interlocked.Decrement(ref process) == 0) resetEvent.Set(); }).Start(); } /* Wait for task to finish */ resetEvent.WaitOne(); Console.WriteLine("Finished.");