它们似乎都能达到相同的目的。我在何时应选择其中之一?
它们似乎都能达到相同的目的。我在何时应选择其中之一?
当您有一个线程正在等待一个或多个事件来执行某些操作时,请使用事件。
如果要限制访问数据结构的线程数量,则使用监视器。
通常,监视器保护资源,而事件告诉您发生了某些事情,例如应用程序关闭。
此外,事件可以命名(请参见OpenExisting方法),这允许它们用于跨不同进程的同步。
在我看来,如果可以的话最好使用 Monitor,Monitor.Wait 和 Monitor.Pulse/PulseAll 用于线程间的信号传递(Manual/AutoResetEvent 也可以),但是 Monitor 更快,并且不使用本地系统资源。而 Manual/AutoResetEvent 需要切换到内核模式并调用本地 win32 调用使用等待句柄。
有一些情况需要使用 Manual/AutoResetEvent,例如,要在进程之间进行信号传递,可以使用命名事件,还有就是在应用程序中信号本机线程。
我只是复述了我在这篇优秀文章中读到的内容。
整篇文章都值得一读,但链接将带您转到讨论事件和监视器等待/脉冲的部分。
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
无法做到这一点。这是这些同步机制行为的根本区别,定义了它们可以使用的场景。Wait
和Pulse
。但是,.NET BCL已经涵盖了大多数流行的信号机制。以下信号机制已经存在。BlockingCollection
类。它本质上不是一种信号机制,但它具有信号机制的特性,并且可以附加数据到信号中。在这种情况下,信号表示集合中有一个项可用,与该信号关联的数据是项本身。本教程详细描述了您需要了解的内容: http://www.albahari.com/threading/
特别是,它将涵盖XXXResetEvent类, http://www.albahari.com/threading/part2.aspx
以及这将涵盖Wait/Pulse: http://www.albahari.com/threading/part4.aspx#_Wait_and_Pulse