おっしゃる通り、ReadDirectoryChangesW
IO Completion で非同期を試みていますが、うまくいきません。具体的には、GetLastError
繰り返し 258 (GetQueuedCompletionStatus
タイムアウト) を返します。
私は構造体を持っています:
typedef struct dirinfo_struct
{
HANDLE hDirFH; // directory handle
OVERLAPPED Overlapped; // overlapped storage
int len_buffer; // buffer length
wchar_t* buffer; // buffer itself
wchar_t* directory_name; // target name
} dirinfo_t;
typedef struct dirmon_struct
{
HANDLE hDirOPPort; // handle to the IO port.
dirinfo_t* dirinfo; // pointer to the struct above.
} dirmon_t;
関連情報を保存するため。これは初期化されます:
dirinfo_t* t = malloc(1*sizeof(dirinfo_t));
dirmon_t* d = malloc(1*sizeof(dirmon_t));
dirinfo_init(t); // does t->buffer = malloc(8192*sizeof(wchar_t));
次に、ディレクトリ ハンドルと COM ポートを作成します。
t->hDirFH = CreateFile(L"C:\\test",
FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
d->dirinfo = t;
d->hDirOPPort = CreateIoCompletionPort(d->dirinfo->hDirFH,
NULL,
(ULONG_PTR)(d->dirinfo),
1);
次に、この情報を d 経由で新しいスレッドに渡します。今、私が持っている新しいスレッドで:
bResultQ = GetQueuedCompletionStatus(d->hDirOPPort, lpBytes,
(ULONG_PTR*)d->dirinfo,
lpOverlapped, 1000);
if ( bResultQ )
{
bResultR = ReadDirectoryChangesW(d->dirinfo->hDirFH,
(void*)d->dirinfo->buffer,
8192, TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_LAST_ACCESS |
FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_SECURITY,
lpReadDirBytes,
&d->dirinfo->Overlapped,
NULL );
}
else
{
printf("GetQueuedCompletionStatus(): Failed, ");
errorcode = GetLastError();
printf("Error Code %d\n", errorcode);
Sleep(500);
}
したがって、これを実行しないように設定すると、ディレクトリが変更されていないため、タイムアウト (258 エラー) が発生します。ただし、ディレクトリを変更してもエラー メッセージが表示されます。つまり、これらの変更は検出されません。これにより、この設定が間違っていると思われます。
何か案は?
警告:
- 皮肉なことに、これは最終的に pywin32 経由で Python に変換されます。ただし、これが C でどのように機能するかを理解するまでは、そこには行きません。
- 同期
ReadDirectoryChangesW
はオプションではありません。イベントが発生しない場合は、スレッドがまだ実行されているかどうかを確認できるように、タイムアウトするスレッドが必要です。 - 私はC++ではなく、特にCで書いています。
FindFirstChangeNotification
などもオプションではありません - ディレクトリの一覧を継続的に比較して、何が変更されたかを調べたくありません。
その他の注意事項:
- ディレクトリが存在します。そのハンドルは NULL ではありません。コンポートハンドルも同様です。
- すべてがスレッドに渡されます
私はコード プロジェクトからCDirectoryChangeWatcherを見てきましたが、C++ の使用とその他の多くのスレッドは別として、自分が何をしているのかわかりません。私が何かを見逃している場合は、遠慮なく指摘してください!
問題のディレクトリをどれだけ変更しても、出力が役立つ場合は、基本的に繰り返されます。
GetQueuedCompletionStatus(): Failed, Error Code 258