Monitor.Wait最初被锁定了吗?

3

背景

我正在编写一个应用程序,它需要执行以下操作:

  1. 我调用 SomeBlockingMethod 方法。
  2. 该方法一直阻塞,直到我从另一个线程调用 SomeUnblockingMethod 方法。
  3. 当调用 SomeUnblockingMethod 方法时,SomeBlockingMethod 中的程序将继续执行。

请注意,我首先要做的事情是调用 SomeBlockingMethod,然后稍后再调用 SomeUnblockingMethod。我想使用 Monitor.Wait/Monitor.Pulse 机制来实现此目的。唯一的问题是,当调用 Monitor.Wait 时,除非涉及的 object 已被其他内容锁定(或者至少我不知道),否则无法初始阻塞...但是,我希望 阻塞 成为我要做的 第一件事情... 所以这就导致了我的问题...

问题

有没有办法实现 Monitor.Wait 并最初阻塞,直到调用 Monitor.Pulse 方法?


你想要使用 Monitor.Wait() 的重载版本,其中可以指定超时时间(例如 Infinity)。 - Sinatr
如果您没有指定超时时间,那么请原谅我删除了第一条评论,因为它将是“Infinity”(http://referencesource.microsoft.com/#mscorlib/system/threading/monitor.cs,8873bad9bee77901)。这样,“Monitor.Wait to initially block until a call to Monitor.Pulse”就已经发生了。 - Sinatr
@YuvalItzchakov 谢谢,是的,有人建议只使用AutoResetEvent。 - Snoop
1
一个 AutoResetEvent 仍然会阻塞调用线程,直到你发出信号。我建议可能有一些解决方案根本不需要它。 - Yuval Itzchakov
1
你不知道如何编写正确的代码,难怪啊。 - Hans Passant
显示剩余7条评论
2个回答

2
您可以使用AutoResetEvent代替。
AutoResetEvent ar = new AutoResetEvent(false); // false set initial state as not signaled

然后,您可以使用ar.WaitOne()来等待,ar.Set()来发出等待进程的信号。
当您想保护资源或者有一个关键区时,应该使用Monitor。如果您想要一个信号机制,那么AutoResetEvent或者ManualResetEvent听起来是更好的选择。

那么您不建议完全不使用监视器吗?为什么? - Snoop
1
@StevieV,这只是另一种可能的解决方案。除非您想要同步不同的进程,否则没有必要从轻量级Monitor切换到AutoResetEvent - Sinatr
我说过你不能,你必须。@StevieV - Hamid Pourjam

2
我不知道问题出在哪里,但你想要的已经是它的正常工作方式:
object _lock = new object();

void SomeBlockingMethod()
{
    lock(_lock)
        Monitor.Wait(_lock);
    ... // here only after pulse
}

void SomeUnblockingMethod()
{
    lock(_lock)
        Monitor.Pulse(_lock);
}

也许您正在多个地方调用SomeBlockingMethod,那么您想使用PulseAll。或者也许在调用SomeBlockingMethod之前会调用SomeUnblockingMethod

对于这个问题,如果阻塞方法已经进入了“锁定”区域,非阻塞方法能否进入该区域?我想非阻塞方法需要进入该区域才能激活阻塞方法。是吗? - Snoop
当您调用Monitor.Wait()时,锁定将被释放,以便其他方法可以获取锁定并发出脉冲。阅读更多 - Sinatr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接