AutoResetEvent – synchronizing threads

AutoResetEvent class allows us to synchronize threads.
There are a few important things to know:
1. Constructor:
If you pass true to the constructor it means that thread which uses this AutoResetEvent is free to go and won’t be blocked (state equal to ‘signaled’). If you pass false – thread will be blocked (‘non-signaled’).

2. WaitOne() method:
It causes that thread checks whether it can go (if signaled – can go; if non-signaled – is blocked and waits here). If it can go it immediately sets state to non-signaled.

3. Set() method:
Sets AutoResetEvent to signaled state – threads won’t be blocked.

No synchronization
Imagine that we have two threads. One prints in loop “Hi!” and the other prints in loop “Hello!”. If we do not synchronize this two threads order of messages is random. See below:

        #region nosync
        public void StartWithoutSynchronization()
        {
            SayHiNoSync();
            SayHelloNoSync();
        }

        private void SayHiNoSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    Console.WriteLine($"Hi! ({i} no sync)");
                    i++;
                }
            });
        }

        private void SayHelloNoSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    Console.WriteLine($"Hello! ({i} no sync)");
                    i++;
                }
            });
        }
        #endregion nosync

resetevent_nosync

Synchronized
Now imagine that we want to have messages in console in following order: “Hi” – “Hello” – “Hi” – “Hello” – “Hi” – “Hello” – …
We can make use of AutoResetEvent. See below:

        #region sync
        AutoResetEvent _autoResetEventHi = new AutoResetEvent(true); //initialized to signaled state - will not block thread
        AutoResetEvent _autoResetEventHello = new AutoResetEvent(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)
                {
                    _autoResetEventHi.WaitOne(); //thread checks whether can go or not
                    Console.WriteLine($"Hi! ({i} sync)");
                    i++;
                    _autoResetEventHello.Set(); //sets the other autoResetEvent to signaled state
                }
            });
        }

        private void SayHelloSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _autoResetEventHello.WaitOne(); //thread checks whether can go or not
                    Console.WriteLine($"Hello! ({i} sync)");
                    i++;
                    _autoResetEventHi.Set(); //sets the other autoResetEvent to signaled state
                }
            });
        }
        #endregion sync

resetevent_sync

Explanation:
Both tasks are started in the same time. _autoResetEventHi is initialized not to block the thread. This thread will imediately set state of _autoResetEventHi to non-signaled. _autoResetEventHello is initialized to non-signaled state and will block the thread.
Console will print out “Hi” message. Then this thread will set _autoResetEventHello to signaled state. It will allow the other thread to finish waiting. The other thread sets immediately state of _autoResetEventHello to non-signaled. Console will print out “Hello”.
Then the first thread can again process the loop and unlock the other thread. The other thread is unblocked, processes the message and unlocks the first one… This is how it works.

Synchronized (with defined waiting timespan)
Additional information: WaitOne method accepts parameter (int). It informs how long thread should wait. If you won’t pass this argument it will wait forever (until it is signaled as default value is -1). If you set i.e. 1000 thread will wait (if is blocked) for one second and then continue processing.

Note the code below. I commented out one line end edited one more.

        private void SayHiSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _autoResetEventHi.WaitOne();
                    Console.WriteLine($"Hi! ({i} sync)");
                    i++;
                    //_autoResetEventHello.Set(); //it means _autoResetEventHello will not be signaled at all!
                }
            });
        }

        private void SayHelloSync()
        {
            int i = 0;
            Task.Run(() =>
            {
                while (i < 50)
                {
                    _autoResetEventHello.WaitOne(5000); //it means thread will wait 5 seconds when blocked
                    Console.WriteLine($"Hello! ({i} sync)");
                    i++;
                    _autoResetEventHi.Set();
                }
            });
        }

The final result in console is the same. The difference is that message “Hi” appears immediately and then we wait 5 seconds for “Hello”. Then “Hi” appears immediately again and again we wait 5 seconds for “Hello”…

Advertisements

One thought on “AutoResetEvent – synchronizing threads

  1. Pingback: ManualResetEvent – synchronizing threads | ArW Software

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