ManualResetEvent – synchronizing threads

ManualResetEvent class allows us to synchronize threads. It’s very similar to AutoResetEvent (see before continuing: AutoResetEvent – synchronizing threads)
The difference is that we need one more thing comparing to AutoResetEvent. ManualResetEvent have one more method – Reset(). It allows us to set non-signaled state (opposite to Set() method).
ManualResetEvent does not set non-signaled state when WaitOne() method is executed (as it happens in AutoResetEvent).

Imagine that we have this familiar code, but with ManualResetEvent instead of AutoResetEvent.

        ManualResetEvent _manualResetEventHi = new ManualResetEvent(true); //initialized to signaled state - will not block thread
        ManualResetEvent _manualResetEventHello = new ManualResetEvent(false); //initialized to non-signaled state - will block thread

        public void StartWithSynchronization()
        {
            //we start both threads in the same time
            SayHiSync();
            SayHelloSync();
        }


        private void SayHiSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _manualResetEventHi.WaitOne();
                    Console.WriteLine($"Hi! ({i} sync)");
                    i++;
                    _manualResetEventHello.Set();
                }
            });
        }

        private void SayHelloSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _manualResetEventHello.WaitOne();
                    Console.WriteLine($"Hello! ({i} sync)");
                    i++;
                    _manualResetEventHi.Set();
                }
            });
        }

It won’t synchronize the threads. We have random order in console. Code below fixes this situation:

        ManualResetEvent _manualResetEventHi = new ManualResetEvent(true); //initialized to signaled state - will not block thread
        ManualResetEvent _manualResetEventHello = new ManualResetEvent(false); //initialized to non-signaled state - will block thread

        public void StartWithSynchronization()
        {
            //we start both threads in the same time
            SayHiSync();
            SayHelloSync();
        }


        private void SayHiSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _manualResetEventHi.WaitOne();
                    Console.WriteLine($"Hi! ({i} sync)");
                    i++;
                    if (i % 2 == 0)
                    {
                        _manualResetEventHi.Reset();
                        _manualResetEventHello.Set();
                    }
                }
            });
        }

        private void SayHelloSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _manualResetEventHello.WaitOne();
                    Console.WriteLine($"Hello! ({i} sync)");
                    i++;
                    if (i % 2 == 0)
                    {
                        _manualResetEventHello.Reset();
                        _manualResetEventHi.Set();
                    }
                }
            });
        }

We have following result in console: Hi – Hi – Hello – Hello – Hi – Hi – Hello – Hello – Hi – Hi – …
It is synchronized again because we added two important lines:
_manualResetEventHi.Reset(); – sets non-signaled thread for the other thread (as it is not done automatically like with AutoResetEvent).
_manualResetEventHello.Reset(); – sets non-signaled thread for the first thread (as it is not done automatically like with AutoResetEvent).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s