为什么即使在显式 ResetEvent 调用后我也不能重用事件?

Why can't I reuse an event even after explicit ResetEvent call?

我想查看对文件所做的更改(我正在等待的事件是更改内容事件,即上次修改日期已更新)

我有这样的代码(实际代码的最小化示例) 我希望 while 循环的每次迭代都会重置事件并可以再次触发,但这并没有发生
为什么它只触发一次更改事件?

int main()
{
    const wchar_t *dir_path = L"C:\Users\IC\AppData\Roaming\JetBrains\CLion2021.3\scratches\";

    HANDLE hDir = ::CreateFileW(
        dir_path,
        FILE_LIST_DIRECTORY,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
        NULL
    );

    FILE_NOTIFY_INFORMATION fni;
    OVERLAPPED overlapped;
    overlapped.hEvent = ::CreateEventA(NULL, FALSE, FALSE, NULL);

    ::ReadDirectoryChangesW(
        hDir,
        &fni,
        sizeof(fni),
        TRUE,
        FILE_NOTIFY_CHANGE_LAST_WRITE,
        NULL,
        &overlapped,
        NULL
    );

    while (true)
    {
        std::vector<HANDLE> all_job_event_handles;
        if (::ResetEvent(overlapped.hEvent) == FALSE)
        {
            printf("ResetEvent failed\n");
            fflush(stdout);
            return 1;
        }
        all_job_event_handles.push_back(overlapped.hEvent);

        DWORD result = ::WaitForMultipleObjects(all_job_event_handles.size(), all_job_event_handles.data(), FALSE, INFINITE);
        if (result == WAIT_FAILED)
        {
            printf("WaitForMultipleObjects failed\n");
            fflush(stdout);
            return 1;
        }

        if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + all_job_event_handles.size())
        {
            printf("file changed\n");
            fflush(stdout);
        }
    }
}

因为那不是 ReadDirectoryChanges 的工作方式。它不会持续向您发送更改。它会向您发送一批更改。你处理它们。您再次调用该函数以告诉系统您需要更多更改。

我在这里找到了函数的正确用法示例:https://gist.github.com/nickav/a57009d4fcc3b527ed0f5c9cf30618f8

一些旁注:

  • 您没有检查 ReadDirectoryChanges 是否成功。这是不好的;如果失败,您将永远挂在 Wait 呼叫上。
  • 您没有 zero-initialize OVERLAPPED 结构。
  • 您将事件创建为 auto-reset 事件(第二个参数是 FALSE)。 ResetEvent 对这样的事件什么都不做。
  • 您添加到向量中的所有事件句柄都是同一个事件对象。您只是重复传递给 WaitForMultipleObjects 的同一事件的 ever-growing 列表。这充其量什么也不做,但最终会失败,因为 WFMO 不允许超过 MAXIMUM_WAIT_OBJECTS 个句柄,而且这个数字相当低(我认为是 32)。
  • 您可能希望在您打开的目录上使用更宽松的共享模式。