EventWaitHandle クラスを使用すると、スレッドは、シグナル通知とシグナルの待機によって相互に通信できます。 イベント待機ハンドル (単にイベントとも呼ばれます) は、1 つ以上の待機スレッドを解放するために通知できる待機ハンドルです。 シグナル通知が行われると、イベント待機ハンドルが手動または自動でリセットされます。 EventWaitHandle クラスは、ローカル イベント待機ハンドル (ローカル イベント) または名前付きシステム イベント待機ハンドル (名前付きイベントまたはシステム イベント、すべてのプロセスに表示) を表すことができます。
注
イベント待機ハンドルは .NET イベントではありません。 デリゲートやイベント ハンドラーは関係しません。 "event" という単語は、従来はオペレーティング システム イベントと呼ばられていたため、また、待機ハンドルに通知する動作は、イベントが発生したことを待機中のスレッドに示しているため、それらを記述するために使用されます。
ローカル イベント待機ハンドルと名前付きイベント待機ハンドルの両方でシステム同期オブジェクトが使用されます。このオブジェクトは SafeWaitHandle ラッパーによって保護され、リソースが確実に解放されます。 Disposeメソッドを使用すると、オブジェクトの使用が完了したらすぐにリソースを解放できます。
自動的にリセットされるイベント待機ハンドル
自動リセット イベントを作成するには、EventResetMode.AutoReset オブジェクトの作成時にEventWaitHandleを指定します。 その名前が示すように、この同期イベントは、1 つの待機中のスレッドを解放した後、通知されると自動的にリセットされます。 Set メソッドを呼び出してイベントを通知します。
自動リセット イベントは、通常、一度に 1 つのスレッドのリソースへの排他的アクセスを提供するために使用されます。 スレッドは、 WaitOne メソッドを呼び出してリソースを要求します。 他のスレッドが待機ハンドルを保持していない場合、メソッドは true を返し、呼び出し元のスレッドはリソースを制御します。
Von Bedeutung
すべての同期メカニズムと同様に、保護されたリソースにアクセスする前に、すべてのコード パスが適切な待機ハンドルを待機していることを確認する必要があります。 スレッド同期は協調的です。
スレッドが待機していないときに自動リセット イベントが通知された場合、スレッドが待機を試みるまで通知されたままになります。 イベントによってスレッドが解放され、直ちにリセットされ、後続のスレッドがブロックされます。
手動でリセットするイベント待機ハンドル
手動リセット イベントを作成するには、EventResetMode.ManualReset オブジェクトの作成時にEventWaitHandleを指定します。 その名前が示すように、この同期イベントは、通知された後に手動でリセットする必要があります。 リセットされるまで、 Reset メソッドを呼び出すことによって、イベント ハンドルを待機するスレッドはブロックすることなく直ちに続行されます。
手動リセットイベントは、囲いのゲートのように機能します。 イベントが通知されない場合、イベントを待機するスレッドは、囲いの中の馬のように待機状態になります。 イベントが通知されると、その Set メソッドを呼び出すことによって、待機しているすべてのスレッドは自由に続行できます。 イベントは、 Reset メソッドが呼び出されるまで通知されたままになります。 これにより、手動リセット イベントは、1 つのスレッドがタスクを完了するまで待機する必要があるスレッドを保持するための理想的な方法になります。
馬がコラルを離れるのと同様に、リリースされたスレッドがオペレーティング システムによってスケジュールされ、実行が再開されるまでに時間がかかります。 すべてのスレッドが実行を再開する前に Reset メソッドが呼び出されると、残りのスレッドは再度ブロックされます。 再開するスレッドとブロックするスレッドは、システムの負荷、スケジューラを待機しているスレッドの数などのランダムな要因によって異なります。 これは、最も一般的な使用パターンであるシグナル通知後にイベントを通知するスレッドが終了しても問題ありません。 すべての待機中のスレッドが再開された後で、イベントを通知したスレッドが新しいタスクを開始する場合は、すべての待機中のスレッドが再開されるまでブロックする必要があります。 それ以外の場合は競合状態になり、コードの動作は予測できません。
自動イベントと手動イベントに共通する機能
通常、ブロック解除されたスレッドが EventWaitHandle メソッドを呼び出すまで、1 つ以上のスレッドがSetでブロックされます。このメソッドは、待機中のスレッドの 1 つ (自動リセット イベントの場合) またはそれらのすべて (手動リセット イベントの場合) を解放します。 スレッドは、静的なEventWaitHandle メソッドを呼び出すことによって、WaitHandle.SignalAndWaitを通知し、それをアトミック操作としてブロックできます。
EventWaitHandle オブジェクトは、静的 WaitHandle.WaitAll および WaitHandle.WaitAny メソッドで使用できます。 EventWaitHandleクラスとMutex クラスの両方がWaitHandleから派生しているため、これらのメソッドで両方のクラスを使用できます。
名前付きイベント
Windows オペレーティング システムでは、イベント待機ハンドルに名前を付けることができます。 名前付きイベントはシステム全体に適用されます。 つまり、名前付きイベントが作成されると、すべてのプロセスのすべてのスレッドに表示されます。 したがって、名前付きイベントを使用して、プロセスとスレッドのアクティビティを同期できます。
イベント名を指定するコンストラクターのいずれかを使用して、名前付きシステム イベントを表す EventWaitHandle オブジェクトを作成できます。
注
名前付きイベントはシステム全体であるため、同じ名前付きイベントを表す複数の EventWaitHandle オブジェクトを持つことができます。 コンストラクターまたは OpenExisting メソッドを呼び出すたびに、新しい EventWaitHandle オブジェクトが作成されます。 同じ名前を指定すると、同じ名前付きイベントを表す複数のオブジェクトが繰り返し作成されます。
名前付きイベントを使用する場合は注意が必要です。 これらはシステム全体であるため、同じ名前を使用する別のプロセスによって、スレッドが予期せずブロックされる可能性があります。 同じコンピューターで実行されている悪意のあるコードでは、これをサービス拒否攻撃の基礎として使用する可能性があります。
アクセス制御セキュリティを使用して、名前付きイベントを表す EventWaitHandle オブジェクトを保護します。可能な場合は、 EventWaitHandleSecurity オブジェクトを指定するコンストラクターを使用します。 SetAccessControlメソッドを使用してアクセス制御セキュリティを適用することもできますが、これにより、イベント待機ハンドルが作成されてから保護されるまでの間に、脆弱性のウィンドウが残ります。 アクセス制御のセキュリティでイベントを保護すると、悪意のある攻撃を防ぐことができますが、意図しない名前の競合の問題は解決されません。
注
EventWaitHandle クラスとは異なり、派生クラスAutoResetEventおよびManualResetEventはローカル待機ハンドルのみを表すことができます。 名前付きシステム イベントを表すことはできません。
こちらも参照ください
.NET