他们似乎都实现了相同的目的。我什么时候会选择其中之一?
4 回答
当您有一个线程正在等待多个事件中的一个或所有事件来做某事时,请使用这些事件。
如果您想通过限制可以访问的线程数来限制对数据结构的访问,请使用监视器。
监视器通常保护资源,而事件会告诉您正在发生的事情,例如应用程序关闭。
此外,可以命名事件(参见 OpenExisting 方法),这允许它们用于跨不同进程的同步。
在我看来,如果可以的话,最好使用 Monitor,Monitor.Wait 和 Monitor.Pulse/PulseAll 用于线程之间的信号发送(如 Manual/AutoResetEvent),但是 Monitor 更快,并且不使用本机系统资源。同样显然 Monitor 是在用户模式下实现并受到管理的,而 Manual/AutoResetEvents 需要切换到内核模式并 p/invoke 到使用等待句柄的本机 win32 调用。
在某些情况下,您需要使用 Manual/AutoResetEvent,例如,在可以使用命名事件的进程之间发出信号,我猜想在您的应用程序中发出本机线程信号。
我只是在重复我在这篇关于线程的优秀文章中读到的内容。
整篇文章都值得一读,但是链接会将您带到详细说明事件和监控等待/脉冲的等待句柄部分。
WaitHandle
当您希望线程发送或接收二进制信号而不需要临界区时,您会使用。另一方面,Monitor.Wait
需要一个关键部分。与 BCL 中的大多数同步机制一样,您提到的两者的使用方式存在一些重叠。但是,不要以为它们实现了相同的目的。Monitor.Pulse
Monitor.Wait
并且Monitor.Pulse
是比 MRE 或 ARE 更原始的同步机制。事实上,您实际上可以只使用Monitor
类来构建 MRE 或 ARE。要理解的最重要的概念是Monitor.Wait
和WaitHandle.WaitOne
方法的不同之处。Wait
并且WaitOne
都将线程置于WaitSleepJoin
状态,这意味着线程变得空闲并且只响应 aThread.Interrupt
或相应的Pulse
orSet
调用。但是,这是一个主要区别,Wait
它将留下一个关键部分并以原子方式重新获取它。WaitOne
根本无法做到这一点。正是这些同步机制的行为方式的根本差异定义了它们可以使用的场景。
在大多数情况下,您会选择 MRE 或 ARE。这些满足了一个线程需要从另一个线程接收信号的大多数情况。但是,如果您想创建自己的信号机制,则需要使用Wait
and Pulse
。但是,同样,.NET BCL 已经涵盖了大多数流行的信号机制。以下信令机制已经存在1.
- ManualResetEvent(或 ManualResetEventSlim)
- 自动复位事件
- 信号量(或 SemaphoreSlim)
- 事件等待句柄
- 倒计时事件
- 屏障
1荣誉奖进入BlockingCollection
班级。它本身不是一种信号机制,但它确实具有信号机制的品质,并具有额外的好处,即您可以将数据附加到信号上。在这种情况下,信号意味着集合中的项目可用,并且与该信号关联的数据是项目本身。
本教程详细描述了您需要了解的内容: http ://www.albahari.com/threading/
特别是,这将涵盖 XXXResetEvent 类,
http://www.albahari.com/threading/part2.aspx
这将涵盖等待/脉冲: http ://www.albahari.com/threading/part4.aspx#_Wait_and_Pulse