2

我一直在尝试使用和理解Microsoft Cloud Mirror示例中的DirectoryWatcher类。它用于监视对目录的更改。老实说,我不认为它报告了所有的变化。无论如何,我对代码的关键部分有疑问,如下:ReadDirectoryChangesW

concurrency::task<void> DirectoryWatcher::ReadChangesAsync()
{
    auto token = _cancellationTokenSource.get_token();
    return concurrency::create_task([this, token]
    {
        while (true)
        {
            DWORD returned;
            winrt::check_bool(ReadDirectoryChangesW(
                _dir.get(),
                _notify.get(),
                c_bufferSize,
                TRUE,
                FILE_NOTIFY_CHANGE_ATTRIBUTES,
                &returned,
                &_overlapped,
                nullptr));

            DWORD transferred;
            if (GetOverlappedResultEx(_dir.get(), &_overlapped, &transferred, 1000, FALSE))
            {
                std::list<std::wstring> result;
                FILE_NOTIFY_INFORMATION* next = _notify.get();
                while (next != nullptr)
                {
                    std::wstring fullPath(_path);
                    fullPath.append(L"\\");
                    fullPath.append(std::wstring_view(next->FileName, next->FileNameLength / sizeof(wchar_t)));
                    result.push_back(fullPath);

                    if (next->NextEntryOffset)
                    {
                        next = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<char*>(next) + next->NextEntryOffset);
                    }
                    else
                    {
                        next = nullptr;
                    }
                }
                _callback(result);
            }
            else if (GetLastError() != WAIT_TIMEOUT)
            {
                throw winrt::hresult_error(HRESULT_FROM_WIN32(GetLastError()));
            }
            else if (token.is_canceled())
            {
                wprintf(L"watcher cancel received\n");
                concurrency::cancel_current_task();
                return;
            }
        }
    }, token);
}

在查看了另一个问题的答案之后,这是我对上面代码的不理解之处:ReadDirectoryChangesW在先前的调用返回结果之前,代码是否可能会重新调用?还是这段代码确实正确?感谢您的任何意见。

是的,我似乎已经在我的测试中确认在while调用周围应该有另一个循环GetOverlappedResultEx,类似于其他答案中提供的示例代码。我认为通知正在正确触发。

那里不应该也有一个电话CancelIo吗?或者由于某种原因这不是必需的?

4

0 回答 0