我什麼時候會使用 AutoResetEvent 和 ManualResetEvent 而不是 Monitor.Wait()/Monitor.Pulse()? (When would I use AutoResetEvent and ManualResetEvent instead of Monitor.Wait()/Monitor.Pulse()?)


問題描述

我什麼時候會使用 AutoResetEvent 和 ManualResetEvent 而不是 Monitor.Wait()/Monitor.Pulse()? (When would I use AutoResetEvent and ManualResetEvent instead of Monitor.Wait()/Monitor.Pulse()?)

它們似乎都實現了相同的目的。我什麼時候會選擇一個而不是另一個?


參考解法

方法 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.

方法 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.

方法 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.

方法 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

(by NabilSScott LanghamMattBrian Gideontorial)

參考文件

  1. When would I use AutoResetEvent and ManualResetEvent instead of Monitor.Wait()/Monitor.Pulse()? (CC BY‑SA 2.5/3.0/4.0)

#locking #synchronization #multithreading #.net






相關問題

C# / ASP.NET - Web 應用程序鎖定 (C# / ASP.NET - Web Application locking)

在程序文件夾中創建鎖定文件會導致異常 (Creating Lock file in Programs Folder causes exception)

我什麼時候會使用 AutoResetEvent 和 ManualResetEvent 而不是 Monitor.Wait()/Monitor.Pulse()? (When would I use AutoResetEvent and ManualResetEvent instead of Monitor.Wait()/Monitor.Pulse()?)

鎖定一個 JavaScript 函數 (Lock a JavaScript Function)

當只有一個線程寫入共享變量時,我需要鎖嗎? (Do I need a lock when only a single thread writes to a shared variable?)

為什麼 lock(objLock) 比 lock(this) 好 (Why is it better to lock(objLock) than lock(this))

雙重檢查鎖定的修復有什麼問題? (What's wrong with this fix for double checked locking?)

在表格行上調用 Dibs (Calling Dibs on a table row)

我怎樣才能優雅地寫 lock {}? (how can I write lock {} elegantly?)

Double Check Lock 不能在這個 java 代碼上工作? (Doubly Check Lock Dosen't work on this java code?)

LINQPad / LINQ To SQL - 簡單查詢僅在循環內執行時才會引發內存不足 (LINQPad / LINQ To SQL - Simple Query Throws Out of Memory Only When Executed Inside a Loop)

如何在 dynamoDB 中實現 50 次寫入的事務? (How can I implement a transaction of 50 writes in dynamoDB?)







留言討論