简体   繁体   中英

c# Thread sync - AutoResetEvent

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

  • Some threads(AF) 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(AF) 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

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.

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.

Use System.Threading.ManualResetEvent.

Threads AF call mre.WaitOne() to wait on thread(X).

When thread X finishes, calling mre.Set() will wake threads AF.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM