C# Multithreading (7): Manual Thread Notification

2020年4月19日 56点热度 0人点赞 0条评论
内容目录

Differences and Examples

AutoResetEvent and ManualResetEvent are quite similar. The difference lies in that the former is automatic (Auto), while the latter is manual (Manual).

You can run the example below first and then test the differences between the two.

AutoResetEvent Example:

    class Program
    {
        // Thread notification
        private static AutoResetEvent resetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            // Create a thread
            new Thread(DoOne).Start();

            // Continuously send signals to another thread
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // Notification occurs, sets to terminating state
            }
        }

        public static void DoOne()
        {
            Console.WriteLine(① Waiting, please signal me to run);
            resetEvent.WaitOne();

            Console.WriteLine(② Waiting, please signal me to run);

            resetEvent.WaitOne();
            Console.WriteLine(③ Waiting, please signal me to run);

            // ...

            Console.WriteLine(Thread ended);
        }
    }

ManualResetEvent Class Example:

    class Program
    {
        private static ManualResetEvent resetEvent = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            new Thread(DoOne).Start();
            // Continuously send signals to another thread
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // Notification occurs, sets to terminating state
            }
        }

        public static void DoOne()
        {
            Console.WriteLine(Waiting, please signal me to run);
            resetEvent.WaitOne();

            // Subsequent calls are ineffective; the thread will skip directly without waiting
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            Console.WriteLine(Thread ended);
        }
    }

Because the AutoResetEvent object automatically resets to a non-terminating state after the .WaitOne() method has waited for a signal, it is like an automatic barrier at a toll station; once a car passes, the machine automatically closes the barrier.

ManualResetEvent is analogous to a manual barrier; once opened, it requires a manual action to close, otherwise it will remain open indefinitely.

ManualResetEvent is mainly used for more flexible thread signaling scenarios.

ManualResetEvent Class

Represents a thread synchronization event. When a signal is received, the event must be manually reset for it to take effect the next time.

Since the ManualResetEvent class is very close to the AutoManualResetEvent class, it will not be reiterated here.

The main usage differences are:

For the AutoResetEvent class, each time Set(), it skips one WaitOne(). Because it automatically restores, the next time it encounters WaitOne(), it will continue to wait.

For the ManualResetEvent class, after Set(), it does not reset, so once Set() is used, it will allow everything to pass without waiting.

The constructors are as follows:

| Constructor | Description |
|--------------------------------------|-------------|
| ManualResetEvent(Boolean) | Initializes a new instance of the ManualResetEvent class with a boolean that indicates whether to set the initial state to terminating. |

The commonly used methods are as follows:

| Method | Description |
|---------------------------------------|-------------|
| Close() | Releases all resources that are used by the current WaitHandle. |
| Reset() | Sets the event state to non-terminating, causing threads to block. |
| Set() | Sets the event state to signaled, allowing one or more waiting threads to proceed. |
| WaitOne() | Blocks the current thread until the current WaitHandle receives a signal. |
| WaitOne(Int32) | Blocks the current thread until the current WaitHandle receives a signal, using a 32-bit signed integer to specify the time interval (in milliseconds). |
| WaitOne(Int32, Boolean) | Blocks the current thread until the current WaitHandle receives a signal, using a 32-bit signed integer to specify the time interval and indicating whether to exit the synchronization domain before waiting. |
| WaitOne(TimeSpan) | Blocks the current thread until the current instance receives a signal, using TimeSpan to specify the time interval. |
| WaitOne(TimeSpan, Boolean) | Blocks the current thread until the current instance receives a signal, using TimeSpan to specify the time interval and indicating whether to exit the synchronization domain before waiting. |

ManualResetEventSlim

ManualResetEventSlim, compared to ManualResetEvent, can provide better performance when the waiting time is expected to be very short and the event does not cross process boundaries.

From the code usage standpoint, there is not much difference; it is mainly about considering performance under different scenarios for the two types.

There is no need to further elaborate on these two types.

痴者工良

高级程序员劝退师

文章评论