异步使用 ReadDirectoryChangesW 时线程死锁

发布于 2024-07-10 14:06:05 字数 2570 浏览 6 评论 0原文

我想在一个线程中实时监控多个目录的更改,因此我决定使用 ReadDirectoryChangesW() 方法与 GetQueuedCompletionStatus 异步使用。 这是我的代码:

static DWORD WINAPI Routine( LPVOID lParam )
{
    FileSystemWatcher* obj = (FileSystemWatcher*)lParam;

    obj->hDir[0] = CreateFile(
        obj->WatchedDir[0].c_str(),
        GENERIC_READ|GENERIC_WRITE,
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
        NULL
    );

    obj->hDir[1] = CreateFile(
   obj->WatchedDir[1].c_str(),
   GENERIC_READ|GENERIC_WRITE,
   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
   NULL,
   OPEN_EXISTING,
   FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
   NULL
    );

    if( INVALID_HANDLE_VALUE == obj->hDir[0] || INVALID_HANDLE_VALUE == obj->hDir     [1] ) 
{
    return false;
}

obj->IOCPHandle[0] = CreateIoCompletionPort(obj->hDir[0], NULL, 0, 1);
obj->IOCPHandle[1] = CreateIoCompletionPort(obj->hDir[1], NULL, 0, 1);

if (obj->IOCPHandle[0] == INVALID_HANDLE_VALUE || obj->IOCPHandle[1] ==  INVALID_HANDLE_VALUE)
{
    return false;
}

    char buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ];
    FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf;
    DWORD BytesReturned;
    LPOVERLAPPED overLap = NULL;

    m_pFileNotifyInfo = pNotify;
    dirEvents[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
    dirEvents[1] = CreateEvent(NULL, TRUE, FALSE, NULL);*/

    while(true)
    {

    BOOL success = ReadDirectoryChangesW( obj->hDir[0],
    pNotify,
    sizeof(buf),
    true,
    FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME,
    &BytesReturned,
    overLap,
    NULL );
    BOOL success1 = ReadDirectoryChangesW( obj->hDir[1],
    pNotify,
    sizeof(buf),
    true,
    FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME,
    &BytesReturned,
    overLap,    
                 NULL );

    LPOVERLAPPED theOverLap;
    PULONG_PTR lpCompKey = NULL;
    if (GetQueuedCompletionStatus(obj->IOCPHandle[0], &BytesReturned, lpCompKey, &overLap, 100))
    {
    cout<<"First Dir Changed"<<endl;
    }

    if (GetQueuedCompletionStatus(obj->IOCPHandle[1], &BytesReturned, lpCompKey, &overLap, 100))
    {
    cout<<"Second Dir Changed"<<endl;
    }

    cout<<"Nothing happened yet"<<endl;

       }

    return 0;
}

当我运行代码时,无论我为 GetQueuedCompletionStatus() 函数的最后一个参数设置什么值,我的线程都会无缘无故地阻塞。 我不知道为什么我遇到这个问题。 谁能告诉我原因吗? 非常感谢!

I want to monitor in real-time the changes of several directories in one thread, so I decided to use ReadDirectoryChangesW() method asynchronously with GetQueuedCompletionStatus. Here is my code:

static DWORD WINAPI Routine( LPVOID lParam )
{
    FileSystemWatcher* obj = (FileSystemWatcher*)lParam;

    obj->hDir[0] = CreateFile(
        obj->WatchedDir[0].c_str(),
        GENERIC_READ|GENERIC_WRITE,
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
        NULL
    );

    obj->hDir[1] = CreateFile(
   obj->WatchedDir[1].c_str(),
   GENERIC_READ|GENERIC_WRITE,
   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
   NULL,
   OPEN_EXISTING,
   FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
   NULL
    );

    if( INVALID_HANDLE_VALUE == obj->hDir[0] || INVALID_HANDLE_VALUE == obj->hDir     [1] ) 
{
    return false;
}

obj->IOCPHandle[0] = CreateIoCompletionPort(obj->hDir[0], NULL, 0, 1);
obj->IOCPHandle[1] = CreateIoCompletionPort(obj->hDir[1], NULL, 0, 1);

if (obj->IOCPHandle[0] == INVALID_HANDLE_VALUE || obj->IOCPHandle[1] ==  INVALID_HANDLE_VALUE)
{
    return false;
}

    char buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ];
    FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf;
    DWORD BytesReturned;
    LPOVERLAPPED overLap = NULL;

    m_pFileNotifyInfo = pNotify;
    dirEvents[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
    dirEvents[1] = CreateEvent(NULL, TRUE, FALSE, NULL);*/

    while(true)
    {

    BOOL success = ReadDirectoryChangesW( obj->hDir[0],
    pNotify,
    sizeof(buf),
    true,
    FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME,
    &BytesReturned,
    overLap,
    NULL );
    BOOL success1 = ReadDirectoryChangesW( obj->hDir[1],
    pNotify,
    sizeof(buf),
    true,
    FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME,
    &BytesReturned,
    overLap,    
                 NULL );

    LPOVERLAPPED theOverLap;
    PULONG_PTR lpCompKey = NULL;
    if (GetQueuedCompletionStatus(obj->IOCPHandle[0], &BytesReturned, lpCompKey, &overLap, 100))
    {
    cout<<"First Dir Changed"<<endl;
    }

    if (GetQueuedCompletionStatus(obj->IOCPHandle[1], &BytesReturned, lpCompKey, &overLap, 100))
    {
    cout<<"Second Dir Changed"<<endl;
    }

    cout<<"Nothing happened yet"<<endl;

       }

    return 0;
}

Here when I run my code, my thread blocks for no reason, no matter what value I set to the last parameter of GetQueuedCompletionStatus() function. I don't know why I encountered this problem. Can anyone tell my the reason? Many thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我偏爱纯白色 2024-07-17 14:06:05
  1. 您必须指定有效的 OVERLAPPED 结构才能使异步 I/O 工作。 您正在使用 NULL (LPOVERLAPPED overLap = NULL;)。

  2. 并发 I/O 操作必须使用单独的 OVERLAPPED 结构,而不仅仅是一个。

  3. 您确定需要 IOCP 吗? 我只需在 OVERLAPPED 结构中填写 hEvent 并对这些事件执行 WaitForMultipleObjects

  1. You have to specify a valid OVERLAPPED structure for asynchronous I/O to work. You are using NULL (LPOVERLAPPED overLap = NULL;).

  2. Concurrent I/O operations must use separate OVERLAPPED structures, not just one.

  3. Are you sure you need IOCP at all? I would just fill in hEvent in the OVERLAPPED structures and do a WaitForMultipleObjects on these events.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文