我何时使用AutoResetEvent和ManualResetEvent而不是Monitor.Wait()/ Monitor.Pulse()?

时间:2008-10-01 15:13:58

标签: .net multithreading synchronization locking

他们似乎都达到了同样的目的。我何时会选择一个而不是另一个?

4 个答案:

答案 0 :(得分:15)

当你有一个等待一个或所有许多事件的线程做某事时,使用这些事件。

如果要通过限制可以访问数据结构的线程来限制对数据结构的访问,请使用监视器。

监视器通常会保护资源,而事件会告诉您正在发生的事情,例如关闭应用程序。

此外,可以命名事件(请参阅OpenExisting方法),这允许它们用于跨不同进程的同步。

答案 1 :(得分:10)

在我看来,如果可以,最好使用Monitor,Monitor.Wait和Monitor.Pulse / PulseAll用于线程之间的信令(如手动/ AutoResetEvent)但是Monitor更快,并且不使用本机系统资源。显然,Monitor在用户模式下实现并进行管理,而Manual / AutoResetEvents需要切换到内核模式,并且p / invoke out到使用等待句柄的本机win32调用。

在某些情况下,您需要使用Manual / AutoResetEvent,例如,在可以使用命名事件的进程之间发出信号,我想在您的应用程序中发出本机线程的信号。

我只是反驳了我在this excellent article中读到的有关线程的内容。

整篇文章值得一读,但链接会将您带到等待句柄部分,详细说明事件并监视等待/脉冲。

答案 2 :(得分:7)

当您希望线程发送或接收二进制信号需要关键部分时,您将使用WaitHandle。另一方面,Monitor.WaitMonitor.Pulse 需要一个关键部分。与BCL中的大多数同步机制一样,如何使用您提到的两个机制有一些重叠。但是,暂时不要考虑他们实现同样的目的。

Monitor.WaitMonitor.Pulse是比MRE或ARE更原始的同步机制。实际上,您实际上可以使用Monitor类来构建MRE或ARE。要理解的最重要的概念是Monitor.WaitWaitHandle.WaitOne方法的不同之处。 WaitWaitOne都会将线程置于WaitSleepJoin状态,这意味着线程变为空闲状态,只响应Thread.Interrupt或相应的PulseSet致电。但是,这是一个主要的区别,Wait将留下一个关键部分并以原子方式重新获取 WaitOne根本无法做到这一点。这些同步机制的行为方式非常重要,它定义了可以使用它们的场景。

在大多数情况下,您会选择MRE或ARE。这些满足大多数情况,其中一个线程需要从另一个线程接收信号。但是,如果要创建自己的信令机制,则需要使用WaitPulse。但是,再一次,.NET BCL已经涵盖了大多数流行的信令机制。以下信号机制已经存在 1

  • ManualResetEvent(或ManualResetEventSlim)
  • 的AutoResetEvent
  • 信号量(或SemaphoreSlim)
  • EventWaitHandle
  • CountdownEvent

1 荣誉奖提到BlockingCollection课程。它本身不是信令机制,但它确实具有信令机制的特性,并且具有可以将数据附加到信号的额外好处。在这种情况下,信号意味着项目在集合中可用,与该信号相关的数据是项目本身。

答案 3 :(得分:2)

本教程详细介绍了您需要了解的内容: http://www.albahari.com/threading/

特别是,这将涵盖XXXResetEvent类,
http://www.albahari.com/threading/part2.aspx

这将涵盖等待/脉冲: http://www.albahari.com/threading/part4.aspx#_Wait_and_Pulse