MSDNによると: Monitor.Wait Method(Object)
SynchronizationLockException: 呼び出しスレッドは、指定されたオブジェクトのロックを所有していません。
つまり、ロックを取得するために呼び出すのに対し、既にロックを所有Monitor.Wait(Object)
している場合にのみ呼び出すことができます。Monitor.Enter(Object)
必要な理由についてMonitor.Wait
: 実行を継続するための情報が不足していることにスレッドが気付いた場合 (シグナルを待っているなど)、他のスレッドをクリティカル セクションに入れたいと思うかもしれません。すべてのスレッドが同じ前提条件を持っているわけではないからです。
待機中のスレッドが実行を継続するには、ロックを解放する前にMonitor.Pulse(Object)
orを呼び出す必要があります (そうしないと、 と同じ種類の例外が発生します)。Monitor.PulseAll(Object)
Monitor.Wait(Object)
パルスの後、ロックが解放された後にロックを取得する次のスレッドは、必ずしもパルスを受信したスレッドではないことに注意してください。
また、パルスを受信することは、条件が満たされることと同じではないことに注意してください。もう少し待つ必要があるかもしれません:
// make sure to synchronize this correctly ;)
while (ConditionNotMet)
{
Monitor.Wait(mutex);
if (ConditionNotMet) // We woke up, but our condition is still not met
Monitor.Pulse(mutex); // Perhaps another waiting thread wants to wake up?
}