When would I use AutoResetEvent and ManualResetEvent instead of Monitor.Wait()/Monitor.Pulse()?

11,092

Solution 1

Use the events when you've got a thread that is waiting on one of or all of a number of events to do something.

Use the monitor if you want to restrict access to a data structure by limiting how many threads can access it.

Monitors usually protect a resource, whereas events tell you something's happening, like the application shutting down.

Also, events can be named (see the OpenExisting method), this allows them to be used for synchronization across different processes.

Solution 2

In my opinion, it's better to use Monitor if you can, Monitor.Wait and Monitor.Pulse/PulseAll are used for signalling between threads (as are Manual/AutoResetEvent) however Monitor is quicker, and doesn't use a native system resource. Also apparently Monitor is implemented in user mode and is managed, whereas Manual/AutoResetEvents require switching to kernel mode and p/invoke out to native win32 calls that use a wait handle.

There are situations where you would need to use Manual/AutoResetEvent, for example, to signal between processes you can use named events, and I guess to signal native threads in your app.

I am just regurgitating what I have read in this excellent article about threading.

The whole article is worth reading, however the link takes you to the wait handle section that details the events and monitor wait/pulse.

Solution 3

You would use a WaitHandle when you want a thread to send or receive a binary signal without the need for a critical section. Monitor.Wait and Monitor.Pulse on the other hand require a critical section. Like most of the synchronization mechanisms in the BCL there is some overlap in how a the two you mentioned can be used. But, do not think for a moment that they fulfill the same purpose.

Monitor.Wait and Monitor.Pulse are a much more primitive synchronization mechanism than an MRE or ARE. In fact, you can actually build an MRE or ARE using nothing more than the Monitor class. The most important concept to understand is how the Monitor.Wait and WaitHandle.WaitOne methods differ. Wait and WaitOne will both put the thread in the WaitSleepJoin state which means the thread becomes idle and only responds to either a Thread.Interrupt or the respective Pulse or Set call. But, and this is a major difference, Wait will leave a critical section and reacquire it in an atomic manner. WaitOne simply cannot do this. It is a difference so fundamental to the way these synchronization mechanisms behave that defines the scenarios in which they can be used.

In most situations you would choose an MRE or ARE. These satisfy most situations where one thread needs to receive a signal from another. However, if you want to create your own signaling mechanism then you would need to use Wait and Pulse. But, again, the .NET BCL has most of the popular signaling mechanisms covered already. The following signaling mechanisms already exist1.

  • ManualResetEvent (or ManualResetEventSlim)
  • AutoResetEvent
  • Semaphore (or SemaphoreSlim)
  • EventWaitHandle
  • CountdownEvent
  • Barrier

1An honorable mention goes to the BlockingCollection class. It is not a signaling mechanisms per se, but it does have the qualities of a signaling mechanism with the added benefit that you can attach data to the signal. In this case the signal means that an item is available in the collection and the data associated with that signal is the item itself.

Solution 4

This tutorial has detailed descriptions of what you'll need to know: http://www.albahari.com/threading/

In particular, this will cover the XXXResetEvent classes,
http://www.albahari.com/threading/part2.aspx

and this will cover Wait/Pulse : http://www.albahari.com/threading/part4.aspx#_Wait_and_Pulse

Share:
11,092
Admin
Author by

Admin

Updated on June 15, 2022

Comments

  • Admin
    Admin almost 2 years

    They both seem to fulfill the same purpose. When would I chose one over the other?