从不同步的代码块调用Monitor和Object同步方法

时间:2013-12-04 21:02:06

标签: c# multithreading

我正在检查我的队列是否已满或

lock (SizeQueueProperty.Locker)
{
    while (_queue.Count >= _maxSize)
    {
        SizeQueueProperty.Waiting = true;
        Monitor.Wait(SizeQueueProperty.Locker);
    }
    _queue.Enqueue(item);
    if (_queue.Count == 1)
    {
        // wake up any blocked dequeue
        SizeQueueProperty.Waiting = false;
        Monitor.PulseAll(SizeQueueProperty.Locker);
    }
}


public static class SizeQueueProperty
{
    public volatile static object Locker = new object();
    public volatile static bool Waiting;
}

如果然后在另一个线程中的另一个类中检查此代码:

if (SizeQueueProperty.Waiting)
{
    Log.Info("Waiting for continue on crawling");
    Monitor.Wait(SizeQueueProperty.Locker);
    ....
    More code
}

...

已满,我想等待该队列变空,然后继续执行线程。但我总是得到meesage:

  

从非同步调用对象同步方法   代码块。

为什么?

3 个答案:

答案 0 :(得分:2)

来自文档的

Wait方法。

  

释放对象的锁定并阻止当前线程直到它   重新获得锁定。

只有在您持有Wait

时,才应在对象上调用lock
if (SizeQueueProperty.Waiting)
{
    Log.Info("Waiting for continue on crawling");
    Monitor.Wait(SizeQueueProperty.Locker);
}

此代码似乎没有锁定,是吗?

答案 1 :(得分:0)

我也有这个问题 - "对象同步方法是从一个不同步的代码块中调用的。"我将Monitor.Enter(变量)称为值类型。在我的实例中,它是一个整数。我通过使用对象的实例解决了它。 RowIndex作为我想要锁定的整数。所以我把我的代码改为:

Private SyncObj As New Object

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Threading.Monitor.Enter(SyncObj)
        ToolStripProgressBar1.Value = RowIndex / Dt.Rows.Count * 100
        ToolStripStatusLabel1.Text = (Dt.Rows.Count - RowIndex).ToString & " left"
        Threading.Monitor.Exit(SyncObj)
End Sub

然后在我的其他线程中,我会在对RowIndex进行任何更改之前锁定SyncObj。工作得很好!

答案 2 :(得分:0)

在我看来,.NET 4.5中原始代码的需要可以通过使用来实现 BlockingCollection