次の方法で共有


System.Threading.Monitor.Wait メソッド

この記事では、この API のリファレンス ドキュメントに補足的な解説を提供します。

Wait(Object, Int32, Boolean) メソッド

このメソッドは、 obj パラメーターの排他ロックを再取得するまで戻りません。

指定されたオブジェクトのロックを現在所有しているスレッドは、別のスレッドがオブジェクトにアクセスできるように、オブジェクトを解放するためにこのメソッドを呼び出します。 呼び出し元は、ロックの再取得を待機している間にブロックされます。 このメソッドは、別のスレッドの操作の結果として発生する状態変更を呼び出し元が待機する必要がある場合に呼び出されます。

タイムアウトにより、別のスレッドが最初に Pulse メソッドまたは PulseAll メソッドを呼び出さずにロックを解放した場合に、現在のスレッドが無期限にブロックされないようにします。 また、スレッドを準備完了キューに移動し、待機キューの前にある他のスレッドをバイパスして、ロックをより早く再取得できるようにします。 スレッドは、 Wait メソッドの戻り値をテストして、タイムアウト前にロックを再取得したかどうかを判断できます。スレッドは、待機に入る原因となった条件を評価し、必要に応じて Wait メソッドを再度呼び出すことができます。

スレッドが Waitを呼び出すと、ロックが解放され、待機キューに入ります。 この時点で、準備完了キュー内の次のスレッド (存在する場合) がロックの制御を受け入れられます。 Wait呼び出されたスレッドは、ロックを保持するスレッドがPulseAllを呼び出すか、またはキュー内の次のスレッドであり、ロックを保持するスレッドがPulse呼び出されるまで待機キューに残ります。 ただし、別のスレッドがこのオブジェクトのPulseまたはPulseAllメソッドを呼び出す前にmillisecondsTimeoutが経過すると、ロックを回復するために元のスレッドが準備完了キューに移動されます。

millisecondsTimeout パラメーターにInfiniteが指定されている場合、ロックの所有者がPulseまたはPulseAllを呼び出さない限り、このメソッドは無期限にブロックされます。 millisecondsTimeoutが 0 の場合、Wait呼び出すスレッドはロックを解放し、すぐに準備完了キューに入ってロックを回復します。

呼び出し元は、指定したオブジェクトEnter呼び出された回数に関係なく、Waitを 1 回実行します。 概念的には、 Wait メソッドは、呼び出し元がオブジェクトに対して Enter 呼び出した回数を格納し、ロックされたオブジェクトを完全に解放するために必要な回数だけ Exit 呼び出します。 呼び出し元は、オブジェクトの再取得を待機している間にブロックします。 呼び出し元がロックを再取得すると、システムは呼び出し元の保存されたEnter数を復元するために必要な回数Enter呼び出します。 Wait呼び出し元は、指定されたオブジェクトのロックのみを解放します。呼び出し元が他のオブジェクトのロックの所有者である場合、これらのロックは解放されません。

同期されたオブジェクトには、現在ロックを保持しているスレッドへの参照、ロックを取得する準備ができているスレッドを含む準備完了キューへの参照、オブジェクトの状態の変更の通知を待機しているスレッドを含む待機キューへの参照など、いくつかの参照が保持されます。

PulsePulseAll、およびWaitメソッドは、同期されたコード ブロック内から呼び出す必要があります。

Pulse メソッドの解説では、スレッドが待機していないときにPulseが呼び出された場合の動作について説明します。

Wait(Object, TimeSpan, Boolean) メソッド

このメソッドは、 obj パラメーターの排他ロックを再取得するまで戻りません。

指定されたオブジェクトのロックを現在所有しているスレッドは、別のスレッドがオブジェクトにアクセスできるように、オブジェクトを解放するためにこのメソッドを呼び出します。 呼び出し元は、ロックの再取得を待機している間にブロックされます。 このメソッドは、別のスレッドの操作の結果として発生する状態変更を呼び出し元が待機する必要がある場合に呼び出されます。

タイムアウトにより、別のスレッドが最初に Pulse メソッドまたは PulseAll メソッドを呼び出さずにロックを解放した場合に、現在のスレッドが無期限にブロックされないようにします。 また、スレッドを準備完了キューに移動し、待機キューの前にある他のスレッドをバイパスして、ロックをより早く再取得できるようにします。 スレッドは、 Wait メソッドの戻り値をテストして、タイムアウト前にロックを再取得したかどうかを判断できます。スレッドは、待機に入る原因となった条件を評価し、必要に応じて Wait メソッドを再度呼び出すことができます。

スレッドが Waitを呼び出すと、ロックが解放され、待機キューに入ります。 この時点で、準備完了キュー内の次のスレッド (存在する場合) がロックの制御を受け入れられます。 Wait呼び出されたスレッドは、ロックを保持するスレッドがPulseAllを呼び出すか、またはキュー内の次のスレッドであり、ロックを保持するスレッドがPulse呼び出されるまで待機キューに残ります。 ただし、別のスレッドがこのオブジェクトのPulseまたはPulseAllメソッドを呼び出す前にtimeoutミリ秒が経過すると、ロックを回復するために元のスレッドが準備完了キューに移動されます。

timeout パラメーターに -1 ミリ秒を表すTimeSpanが指定されている場合、ロック呼び出しの所有者がPulseまたはPulseAllしない限り、このメソッドは無期限にブロックされます。 timeoutが 0 ミリ秒の場合、Wait呼び出すスレッドはロックを解放し、すぐに準備完了キューに入ってロックを回復します。

呼び出し元は、指定したオブジェクトEnter呼び出された回数に関係なく、Waitを 1 回実行します。 概念的には、 Wait メソッドは、呼び出し元がオブジェクトに対して Enter 呼び出した回数を格納し、ロックされたオブジェクトを完全に解放するために必要な回数だけ Exit 呼び出します。 呼び出し元は、オブジェクトの再取得を待機している間にブロックします。 呼び出し元がロックを再取得すると、システムは呼び出し元の保存されたEnter数を復元するために必要な回数Enter呼び出します。 Wait呼び出し元は、指定されたオブジェクトのロックのみを解放します。呼び出し元が他のオブジェクトのロックの所有者である場合、これらのロックは解放されません。

同期されたオブジェクトには、現在ロックを保持しているスレッドへの参照、ロックを取得する準備ができているスレッドを含む準備完了キューへの参照、オブジェクトの状態の変更の通知を待機しているスレッドを含む待機キューへの参照など、いくつかの参照が保持されます。

PulsePulseAll、およびWaitメソッドは、同期されたコード ブロック内から呼び出す必要があります。

Pulse メソッドの解説では、スレッドが待機していないときにPulseが呼び出された場合の動作について説明します。

コンテキストを終了する

Wait メソッドが既定以外のマネージド コンテキスト内から呼び出されない限り、exitContext パラメーターは無効です。 これは、スレッドが ContextBoundObjectから派生したクラスのインスタンスの呼び出し内にある場合に発生する可能性があります。 Stringなど、ContextBoundObjectから派生していないクラスで現在メソッドを実行している場合でも、ContextBoundObjectが現在のアプリケーション ドメイン内のスタック上にある場合は、既定以外のコンテキストにすることができます。

コードが既定以外のコンテキストで実行されている場合、exitContexttrueを指定すると、スレッドは既定以外のマネージド コンテキスト (つまり、既定のコンテキストに遷移) を終了してから、Wait メソッドを実行します。 Wait メソッドの呼び出しが完了すると、元の既定以外のコンテキストに戻ります。

これは、コンテキスト バインド クラスに SynchronizationAttribute 属性が適用されている場合に便利です。 その場合、クラスのメンバーに対するすべての呼び出しが自動的に同期され、同期ドメインはクラスのコード全体です。 メンバーの呼び出し履歴内のコードがWait メソッドを呼び出し、exitContexttrueを指定すると、スレッドは同期ドメインを終了し、オブジェクトの任意のメンバーへの呼び出しでブロックされるスレッドを続行できます。 Wait メソッドが戻るときに、呼び出しを行ったスレッドは、同期ドメインの再入力を待機する必要があります。