profile for TheDaveJay at Stack Overflow, Q&A for professional and enthusiast programmers

Tuesday 16 November 2010

C#.Net - Waiting for Threads using WaitHandles and AutoResetEvents

There have been a few times where I had 1 main executing thread which needed to break huge tasks into smaller pieces, and then have the main thread wait for the smaller tasks to complete.For Example, and ASPX page.


The way Im going to show us makes use of WaitHandle objects and AutoResetEvents.


Review the code below and see how they are used. If you would like to discuss how they actually work, please leave a comment.


class Program{

 static void Main(string[] args)
 {
    WaitHandle[] waitHandles = new WaitHandle[5];
    Console.WriteLine("Starting Threads");

    for (int ii = 0; ii < 5; ii++)
    {
  //create the wait handle and set it not to be signaled. The means when its asked to wait,   no thread can carry on.
    waitHandles[ii] = new AutoResetEvent(false);
    Thread thread = new Thread(() => { DoWork(ii.ToString(), (AutoResetEvent)waitHandles   [ii]); });
    thread.Start();
    //wait 1 second before carrying on
    Thread.Sleep(1000);

    Console.WriteLine("Waiting for threads to complete");
    //Wait for the threads
    WaitHandle.WaitAll(waitHandles.ToArray());
    Console.WriteLine("Allthreads are complete!");
    Console.Read();

 }

 static void DoWork(string name, AutoResetEvent waitHandle)
 {
    try
    {
    Console.WriteLine(string.Format("Doing Work on thread {0}", name));
    //make the do work pretend its doing something improtant like updating a DB.
    Thread.Sleep(5000);
    Console.WriteLine(string.Format("Doing Done", name));
    }
    finally
    {
    //set the wait handle. This marks it as signaled and other threads can carry on.
    waitHandle.Set();
    }
 }


 When it comes to using these object, you MUST TAKE CARE. Its very easy to leave a thread in an infinate waiting loop. For example, if an exception was thrown in the DoWork() method, and I didnt have the AutoResetEvent set in the finally clause, you could see how the event may never be set. So take great care when it comes to multi threading!


}

1 comment:

  1. The one thing I should mention is that there is a limit to how many WaitHandles can be waited for at once. Last I tried using over 64, and error was thrown. In that case, I has to manually loop through each wait handle and waitone(). After some googling, it turns out that waiting for more than 64 at once stalls the message pump, so take great care.

    ReplyDelete