Да, производитель (или инсертор) будет заблокирован, пока блокировка удерживается потребителем.Обратите внимание, что блокировка снимается вызовом Monitor.Wait
и затем повторно запрашивается, когда поток управления возвращается обратно к вызывающей стороне.Все это предполагает, что ваш производитель пытается получить такую же блокировку.
Как примечание: способ кодирования потребителя несколько менее эффективен, чем мог бы быть.Поскольку у вас есть оператор continue
, я должен предположить, что цикл while
оборачивает lock
, что, вероятно, делает ваш код более похожим на следующее.
object msg = null;
while (msg == null)
{
lock (MsgQueue)
{
if (MsgQueue.Count == 0)
{
Monitor.Wait(MsgQueue);
continue;
}
msg = MsgQueue.Dequeue();
}
}
Это можно изменить, чтобыусловие ожидания перепроверяется внутри блока lock
.Таким образом, вам не нужно снимать и повторно захватывать блокировку для выполнения проверки.
object msg = null;
lock (MsgQueue)
{
while (MsgQueue.Count == 0)
{
Monitor.Wait(MsgQueue);
}
msg = MsgQueue.Dequeue();
}
Опять же, поскольку я вижу оператор continue
, я предполагаю, что вы знаете, что условие ожидания всегда должно быть перепроверенопосле Wait
.Но на случай, если вы не знаете об этом требовании, я изложу его здесь, потому что оно важно.
Если условие ожидания не перепроверено и имеется 2 или более потребителей, то один из них может попасть внутрьзаблокировать и снять с очереди последний элемент.Это все еще может произойти, даже если другой потребитель был перемещен из очереди ожидания в очередь готовности посредством вызова на номер Pulse
или PulseAll
, но у него не было возможности повторно получить блокировку перед первым потребителем.Очевидно, что без повторной проверки потребитель может попытаться работать в пустой очереди.Не имеет значения, используется ли Pulse
или PulseAll
на стороне производства.Проблема все еще существует, потому что Monitor
не дает предпочтения Wait
выше Enter
.
Обновление:
Я забыл указатьчто если вы используете .NET 4.0, вы можете воспользоваться BlockingCollection , который является реализацией очереди блокировки.Это безопасно для нескольких производителей и потребителей и делает всю блокировку за вас, если очередь пуста.