指定したディレクトリの変更を監視し、正確な変更情報を取得したいと考えています。そこで、ReadDirectoryChangesW()関数を使用することにしました。しかし、非同期で使用したいのです。つまり、ディレクトリに変更がない場合にワーカー スレッドをブロックしたくないということです。
これどうやってするの?
指定したディレクトリの変更を監視し、正確な変更情報を取得したいと考えています。そこで、ReadDirectoryChangesW()関数を使用することにしました。しかし、非同期で使用したいのです。つまり、ディレクトリに変更がない場合にワーカー スレッドをブロックしたくないということです。
これどうやってするの?
私はI/O完了ポートで使用する傾向がありますReadDirectoryChangesW()
。これは、IOCPにサービスを提供し、ReadDirectoryChangesW()へのすべての呼び出しの結果を処理する単一のスレッドを持つことができるため、複数のディレクトリを監視する場合に適しています。
まず、を呼び出してIOCPを作成しますCreateIoCompletionPort()
。GetQueuedCompletionStatus()
非同期ディレクトリの変更を呼び出して処理するスレッドを開始します。
次に、監視するディレクトリごとに。まず、通常どおりディレクトリハンドルを開きます。次に、IOCPハンドルを呼び出して渡すことにより、IOCPに関連付けますCreateIoCompletionPort()
(詳細については、ドキュメントを参照してください)。最後に、ドキュメントで詳しく説明されているように、を呼び出しReadDirectoryChangesW()
て渡します。呼び出しが返され、成功すると、IOCPにサービスを提供するために作成したスレッドOVERLAPPED
の結果として結果が利用可能になります。GetQueuedCompletionStatus()
ReadDirectoryChnagesW()のMSDNドキュメントから:
非同期完了の場合、次の3つの方法のいずれかで通知を受け取ることができます。
- GetOverlappedResult関数を使用します。GetOverlappedResultを介して通知を受信するには、lpCompletionRoutineパラメーターで完了ルーチンを指定しないでください。OVERLAPPED構造体のhEventメンバーを必ず一意のイベントに設定してください。
- GetQueuedCompletionStatus関数を使用します。GetQueuedCompletionStatusを介して通知を受信するには、lpCompletionRoutineで完了ルーチンを指定しないでください。CreateIoCompletionPort関数を呼び出して、ディレクトリハンドルhDirectoryを完了ポートに関連付けます。
- 完了ルーチンを使用します。完了ルーチンを介して通知を受信するには、ディレクトリを完了ポートに関連付けないでください。lpCompletionRoutineで完了ルーチンを指定します。このルーチンは、スレッドがアラート可能な待機状態にあるときに操作が完了またはキャンセルされるたびに呼び出されます。OVERLAPPED構造体のhEventメンバーはシステムによって使用されないため、自分で使用できます。