他们似乎都达到了同样的目的。我何时会选择一个而不是另一个?
答案 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.Wait
和Monitor.Pulse
需要一个关键部分。与BCL中的大多数同步机制一样,如何使用您提到的两个机制有一些重叠。但是,暂时不要考虑他们实现同样的目的。
Monitor.Wait
和Monitor.Pulse
是比MRE或ARE更原始的同步机制。实际上,您实际上可以使用Monitor
类来构建MRE或ARE。要理解的最重要的概念是Monitor.Wait
和WaitHandle.WaitOne
方法的不同之处。 Wait
和WaitOne
都会将线程置于WaitSleepJoin
状态,这意味着线程变为空闲状态,只响应Thread.Interrupt
或相应的Pulse
或Set
致电。但是,这是一个主要的区别,Wait
将留下一个关键部分并以原子方式重新获取 。 WaitOne
根本无法做到这一点。这些同步机制的行为方式非常重要,它定义了可以使用它们的场景。
在大多数情况下,您会选择MRE或ARE。这些满足大多数情况,其中一个线程需要从另一个线程接收信号。但是,如果要创建自己的信令机制,则需要使用Wait
和Pulse
。但是,再一次,.NET BCL已经涵盖了大多数流行的信令机制。以下信号机制已经存在 1 。
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