6

I have been using an AutoResetEvent to do synchronisation between threads.

  • Some threads(A-F) call autoresetevent.WaitOne(); while waiting for another thread(X) to finish its work
  • whilst the thread(X) owning the autoresetevent does its work and then calls .Set();

However only one of the waiting threads(A-F) is unblocked. - how can i get them ALL to unblock when thread(X) finishes it's work?

I guess I am using the wrong synchronisation primitive - what should i be using and how?

Code samples would be ideal

wonea
  • 4,783
  • 17
  • 86
  • 139
GreyCloud
  • 3,030
  • 5
  • 32
  • 47
  • 1
    Sounds like you want to synchronize the A-F threads as well. More signals or a ManualResetEvent + Interlocked counter might work. – Marvin Smit Feb 12 '11 at 12:12
  • problem is that i dont know how many threads there will be in A-F so i cant call set the right number of times – GreyCloud Feb 12 '11 at 12:13
  • 1
    Are you looking for [Monitor.PulseAll](http://msdn.microsoft.com/en-us/library/system.threading.monitor.pulseall.aspx)? – Ani Feb 12 '11 at 12:29
  • @Ani how would i use monitor.pulseAll ? would it be better than the manualresetevent mentioned below? – GreyCloud Feb 12 '11 at 12:32
  • you should probebly consider ReaderWriterLockSlim – AK_ Feb 12 '11 at 12:53
  • @Hellfrost - what are the advantages of ReaderWriterLockSlim ? – GreyCloud Feb 12 '11 at 13:44
  • that it's designed exactly for a producer\consumer scenario, and thats what i assume you are looking for. Also you have a lot of useful stuff in the System.Collection.Concurent – AK_ Feb 12 '11 at 14:02

3 Answers3

4

Is the ManualResetEvent what you are looking for?

It will stay set until it is reset by some thread.

Somewhere in your code you must know when to Reset it. This might be a simple counter or collection of spawned threads.

Emond
  • 50,210
  • 11
  • 84
  • 115
  • ah ha! that sounds about right! "When the controlling thread completes the activity, it calls Set to signal that the waiting threads can proceed. All waiting threads are released." i'll give it a go ! – GreyCloud Feb 12 '11 at 12:18
  • yep that's got it :) no idea why the manual & auto names were chosen they are not very descriptive – GreyCloud Feb 12 '11 at 12:31
  • :) Auto automatically resets, Manual needs an explicit, or manual, action for the Event to be Set. I am glad it worked. – Emond Feb 12 '11 at 12:34
  • There's a better example/description of ManualResetEvent in this link: http://stackoverflow.com/a/3228242/1507899 – RJB Jan 31 '14 at 23:25
3

Suppose you have this code:

class Program
{
    static void Main(string[] args)
    {
        var are = new AutoResetEvent(false);

        for (int i = 0; i < 10; i++)
        {
            var j = i;
            new Thread(() =>
            {
                Console.WriteLine("Started {0}", j);
                are.WaitOne();
                Console.WriteLine("Continued {0}", j); 
            }).Start();
        }

        are.Set();

        Console.ReadLine();
    }
}

You would then get output such as this:

Started 0
Started 1
Started 2
Started 3
Started 4
Started 5
Started 6
Started 7
Started 8
Continued 0
Started 9

But if you instead use ManualResetEvent:

class Program
{
    static void Main(string[] args)
    {
        var mre = new ManualResetEvent(false);

        for (int i = 0; i < 10; i++)
        {
            var j = i;
            new Thread(() =>
            {
                Console.WriteLine("Started {0}", j);
                mre.WaitOne();
                Console.WriteLine("Continued {0}", j); 
            }).Start();
        }

        mre.Set();

        Console.ReadLine();
    }
}

Then you'll get what I guess is the expected behavior:

Started 0
Started 1
Started 2
Started 3
Started 4
Started 5
Started 6
Started 7
Started 8
Started 9
Continued 1
Continued 8
Continued 7
Continued 4
Continued 5
Continued 6
Continued 3
Continued 0
Continued 9
Continued 2

Of course, as the name implies, ManualResetEvent needs to be manually reset, whereas AutoResetEvent automatically resets after the first WaitOne has released its thread.

Markus Johnsson
  • 3,949
  • 23
  • 30
  • Thanks for the code samples (+1) that is the problem and solution i was experiancing. Accepted Emo for being first. Still dont get the naming of these two classes! – GreyCloud Feb 12 '11 at 12:31
  • Note that Markus Johnsson didn't call mre.Reset() (to do the manual reset). You may want to do that. – Olhovsky Feb 13 '11 at 03:38
0

Use System.Threading.ManualResetEvent.

Threads A-F call mre.WaitOne() to wait on thread(X).

When thread X finishes, calling mre.Set() will wake threads A-F.

In thread X, reset your mre to the base state by doing mre.Reset().

Olhovsky
  • 5,466
  • 3
  • 36
  • 47