我看完这篇文章后的印象是,更好地使用Monitor/Lock进行线程同步,因为它不使用本地资源。
以下是文章第5页的引用:
“Monitor.Wait/Pulse并不是在一个线程中等待某些事情发生并告诉该线程已经发生的唯一方法。Win32程序员已经使用各种其他机制很长时间了,这些机制由AutoResetEvent、ManualResetEvent和Mutex类提供,它们都是从WaitHandle派生而来的。所有这些类都在System.Threading命名空间中。(Win32信号量机制没有.NET 1.1中的托管包装器。在.NET 2.0中存在,但如果您需要在此之前使用它,则可以使用P/Invoke自己包装它或编写自己的计数信号量类。)”
“有些人可能会惊讶地发现,使用这些类比使用各种Monitor方法要慢得多。我认为这是因为从托管代码到本机Win32调用再返回来的过程开销大,与Monitor提供的完全托管视图相比,这是昂贵的。一位读者也解释说,监视器是在用户模式下实现的,而使用等待句柄需要切换到内核模式,这相当昂贵。”
但是,自从发现SO并阅读了一些问题/答案后,我开始怀疑自己关于在何时使用每种方法的理解。许多人似乎建议在Monitor.Wait/Pulse能够完成任务的情况下使用Auto/ManualResetEvent。有人能向我解释一下什么时候应该使用基于WaitHandle的同步而不是Monitor吗?
谢谢
以下是文章第5页的引用:
“Monitor.Wait/Pulse并不是在一个线程中等待某些事情发生并告诉该线程已经发生的唯一方法。Win32程序员已经使用各种其他机制很长时间了,这些机制由AutoResetEvent、ManualResetEvent和Mutex类提供,它们都是从WaitHandle派生而来的。所有这些类都在System.Threading命名空间中。(Win32信号量机制没有.NET 1.1中的托管包装器。在.NET 2.0中存在,但如果您需要在此之前使用它,则可以使用P/Invoke自己包装它或编写自己的计数信号量类。)”
“有些人可能会惊讶地发现,使用这些类比使用各种Monitor方法要慢得多。我认为这是因为从托管代码到本机Win32调用再返回来的过程开销大,与Monitor提供的完全托管视图相比,这是昂贵的。一位读者也解释说,监视器是在用户模式下实现的,而使用等待句柄需要切换到内核模式,这相当昂贵。”
但是,自从发现SO并阅读了一些问题/答案后,我开始怀疑自己关于在何时使用每种方法的理解。许多人似乎建议在Monitor.Wait/Pulse能够完成任务的情况下使用Auto/ManualResetEvent。有人能向我解释一下什么时候应该使用基于WaitHandle的同步而不是Monitor吗?
谢谢
Monitor.Wait
上阻塞,第三个线程通过Monitor.Pulse
设置/信号事件,只有一个等待的线程会被唤醒,因为此代码使用了Monitor.Pulse
而不是Monitor.PulseAll
。这是因为Monitor.Pulse
最多唤醒“一个线程”,而WaitHandles /底层Win32事件API释放“所有等待的线程”。请注意,这并不意味着“您不能使用Monitors实现ManualResetEvents”,只是“此特定实现不满足ManualReset事件的‘粘性’属性”。 - MrCCMonitor.Pulse
的行为与AutoResetEvent
相当。暗示它不可靠或不稳定,因为你正在寻找 ManualReset 行为似乎不公平。 如果你想要 ManualReset(信号保持设置),那么使用ManualResetEvent
,但如果你想要 AutoReset,则Monitor.Pulse
通常可以是一个更好的解决方案。你可以简化你的代码,并避免在错误的时间处置显式事件可能会出现的错误。 - Orion Edwards