我一直在尝试使用和理解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
吗?或者由于某种原因这不是必需的?