- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对 ReadDirectoryChangesW 的奇怪行为感到困惑,错误为 995。下面解释了场景。
FileHandle 是使用 CreateFileW 获得的。
在步骤 1 中获得的文件句柄用于 ReadDirectoryChangesW。成功并向服务器发送请求
轮询 10 秒,如果服务器未生成更改通知,则使用 cancelIo 取消 chnagenotify 请求。它发送取消和服务器响应。
现在再次使用在步骤 1 中获得的文件句柄通过 ReadDirectoryChangesW 设置更改通知,它失败并显示“995 - 由于线程退出或应用程序请求,I/O 操作已中止。”此步骤没有向服务器发送实际请求。
立即使用在步骤 1 中获得的文件句柄再次调用 ReadDirectoryChangesW & 它成功并向服务器发送请求。
第 3、4、5 步在一个循环中重复,每个备用 ReadDirectoryChangesW 失败并返回 995,紧接着下一个成功。
谁能告诉我这是怎么回事?下面是代码
void setnotify(WCHAR* _path)
{
OVERLAPPED _overlapped;
HANDLE _handle;
char _buffer[8192] = {0};
DWORD _bufferSize = 8192;
CnState _state = CN_READY;
DWORD _inactivityTime = 0;
typedef enum State
{
CN_READY,
CN_REQUEST_PENDING,
CN_RESPONSE_RECEIVED,
CN_REQUEST_CANCELLED
} CnState;
_handle = CreateFileW(_path,
GENERIC_READ, // access
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE, // share
NULL, // sec
OPEN_EXISTING, // disp
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
0);
if (_handle == INVALID_HANDLE_VALUE)
{
exit(-1);
}
memset(&_overlapped, 0, sizeof(OVERLAPPED));
if (!ReadDirectoryChangesW(_handle,
_buffer,
_bufferSize,
true,
0x255,
NULL,
&_overlapped,
NULL)) {
exit(-1);
} else {
_state = CN_REQUEST_PENDING;
wprintf(L"Sent Change notify to Server\n");
}
while (1)
{
if ((_state == CN_REQUEST_PENDING) && (HasOverlappedIoCompleted(&_overlapped))) {
wprintf(L"Response Received from Server\n");
_state = CN_RESPONSE_RECEIVED;
}
if ((_state == CN_RESPONSE_RECEIVED) || (_state == CN_REQUEST_CANCELLED)) {
memset(&_overlapped, 0, sizeof(OVERLAPPED));
_inactivityTime = 0;
if (!ReadDirectoryChangesW(_handle,
_buffer,
_bufferSize,
true,
255,
NULL,
&_overlapped,
NULL)) {
wprintf(L"Sent Change notify to Server Failed.\n");
} else {
wprintf(L"Sent Change notify to Server\n");
_state = CN_REQUEST_PENDING;
}
}
if ((_state == ChangeNotifyRequest::CN_REQUEST_PENDING) &&
(_inactivityTime >= 5000)){
if (CancelIo(_handle)) {
_state = CN_REQUEST_CANCELLED;
wprintf(L"Cancelled Pending Requests.\n");
} else {
wprintf(L"Cancelled failed");
}
}
Sleep(50);
_inactivityTime += 50;
}
}
以下是样本 O/P:
向服务器发送更改通知
已取消挂起的请求。
向服务器发送更改通知
已取消挂起的请求。
向服务器发送更改通知失败。
向服务器发送更改通知
已取消待定请求。
向服务器发送更改通知失败。
向服务器发送更改通知
已取消待定请求。
向服务器发送更改通知失败。
向服务器发送更改通知
最佳答案
您开始一个操作然后取消它,所以它的完成事件将报告一个 ERROR_OPERATION_ABORTED
(995) 错误。但是,您在收到该事件之前就开始了新的操作。当您调用 CancelIo()
时,它只是一个取消请求,原始操作仍在等待中,可能需要一段时间才能真正取消(或者它可能在处理取消请求之前成功完成)。所以,你还是需要等待取消的操作真正完成,然后再处理好或坏的结果,然后再开始下一个操作。
此外,您的代码中还有另外两个错误。
第一次调用 ReadDirectoryChangesW()
时,您将 dwNotifyFilter
参数设置为 0x255
,这是错误的。您实际上只请求了这些过滤位:
FILE_NOTIFY_CHANGE_FILE_NAME
FILE_NOTIFY_CHANGE_ATTRIBUTES
FILE_NOTIFY_CHANGE_LAST_WRITE
FILE_NOTIFY_CHANGE_CREATION
随后的调用将 dwNotifFilter
设置为 255
,这实际上是在请求这些过滤器位:
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
所以,你的过滤是不一致的。你真的不应该首先使用“魔数(Magic Number)”。 Win32 API 具有用于可用标志的 #define
常量,您应该按照预期的方式使用它们。
最后,您没有将 CreateEvent()
中的 Event 对象与 OVERLAPPED
结构相关联。 ReadDirectoryChangesW()
中明确规定了此要求不使用 I/O 完成端口或 I/O 完成回调时的文档。
尝试更像这样的东西:
void setnotify(WCHAR* _path)
{
typedef enum State
{
CN_READY,
CN_REQUEST_PENDING,
CN_REQUEST_COMPLETE
} CnState;
OVERLAPPED _overlapped = {0};
HANDLE _handle;
char _buffer[8192];
DWORD _bufferSize;
CnState _state = CN_READY;
DWORD _inactivityTime;
const DWORD _filter = 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;
_handle = CreateFileW(_path,
GENERIC_READ, // access
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE, // share
NULL, // sec
OPEN_EXISTING, // disp
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
0);
if (_handle == INVALID_HANDLE_VALUE)
{
wprintf(L"Opening Server failed. Error: %u\n", GetLastError());
exit(-1);
}
_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (_overlapped.hEvent == NULL)
{
wprintf(L"Creating Overlapped Event failed. Error: %u\n", GetLastError());
exit(-1);
}
do
{
switch (_state)
{
case CN_READY:
{
_bufferSize = 0;
_inactivityTime = 0;
if (!ReadDirectoryChangesW(_handle,
_buffer,
sizeof(_buffer),
TRUE,
_filter,
&_bufferSize,
&_overlapped,
NULL))
{
wprintf(L"Requesting change notify from Server failed. Error: %u\n", GetLastError());
exit(-1);
}
_state = CN_REQUEST_PENDING;
wprintf(L"Change notify requested from Server\n");
break;
}
case CN_REQUEST_PENDING:
{
if (HasOverlappedIoCompleted(&_overlapped))
{
_state = CN_REQUEST_COMPLETE;
}
else if (_inactivityTime >= 5000)
{
if (CancelIo(_handle))
{
_state = CN_REQUEST_COMPLETE;
wprintf(L"No response in 5 seconds. Cancelling pending request\n");
}
else
wprintf(L"No response in 5 seconds. Cancelling pending request failed. Error: %u\n", GetLastError());
}
else
{
Sleep(50);
_inactivityTime += 50;
}
break;
}
case CN_REQUEST_COMPLETE:
{
if (GetOverlappedResult(_handle, &_overlapped, &_bufferSize, TRUE))
{
wprintf(L"Response received from Server\n");
// use _buffer up to _bufferSize bytes as needed...
}
else if (GetLastError() == ERROR_OPERATION_ABORTED)
{
wprintf(L"Pending request cancelled\n");
}
else
{
wprintf(L"Change notify from Server failed. Error: %u\n", GetLastError());
// handle error as needed...
}
_state = CN_READY:
break;
}
}
}
}
但是,如果您不打算使用 I/O 完成端口或 I/O 完成回调,您可以利用这样一个事实来大大简化代码:您可以更有效地等待 OVERLAPPED
通过等待事件对象发出信号来获得结果,而无需在循环中轮询 OVERLAPPED
状态:
void setnotify(WCHAR* _path)
{
OVERLAPPED _overlapped = {0};
HANDLE _handle;
char _buffer[8192];
DWORD _bufferSize;
const DWORD _filter = 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;
_handle = CreateFileW(_path,
GENERIC_READ, // access
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE, // share
NULL, // sec
OPEN_EXISTING, // disp
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
0);
if (_handle == INVALID_HANDLE_VALUE)
{
wprintf(L"Opening Server failed. Error: %u\n", GetLastError());
exit(-1);
}
_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (_overlapped.hEvent == NULL)
{
wprintf(L"Creating Overlapped Event failed. Error: %u\n", GetLastError());
exit(-1);
}
do
{
_bufferSize = 0;
if (!ReadDirectoryChangesW(_handle,
_buffer,
sizeof(_buffer),
TRUE,
_filter,
&_bufferSize,
&_overlapped,
NULL))
{
wprintf(L"Requesting change notify from Server failed. Error: %u\n", GetLastError());
exit(-1);
}
wprintf(L"Change notify requested from Server\n");
// alternatively, use GetOverlappedResultEx() with a timeout
// instead of WaitForSingleObject() and GetOverlappedResult()
// separately...
if (WaitForSingleObject(_overlapped.hEvent, 5000) == WAIT_TIMEOUT)
{
if (CancelIo(_handle))
wprintf(L"No response in 5 seconds. Cancelling pending request\n");
else
wprintf(L"No response in 5 seconds. Cancelling pending request failed. Error: %u\n", GetLastError());
}
if (GetOverlappedResult(_handle, &_overlapped, &_bufferSize, TRUE))
{
wprintf(L"Response received from Server\n");
// use _buffer up to _bufferSize bytes as needed...
}
else if (GetLastError() == ERROR_OPERATION_ABORTED)
{
wprintf(L"Pending request cancelled\n");
}
else
{
wprintf(L"Change notify from Server failed. Error: %u\n", GetLastError());
// handle error as needed...
}
}
while (true);
}
另请参阅 my earlier answer至 a similar question ,其中解释了您在使用 ReadDirectoryChangesW()
时必须注意的其他一些陷阱,尤其是处理 ERROR_NOTIFY_ENUM_DIR
错误。
关于c++ - 如果之前调用了 CancelIo,则 ReadDirectoryChangesW 失败并显示错误 995,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45760370/
我想知道特定目录的任何更改文件。所以,我想出了 ReadDirectoryChangesW() 和 FindFirstChangeNotification() - FindNextChangeNoti
最初我被链接到这个调用,这样我就可以记录对某个文件的所有访问并捕获对其的所有更改。 我已经完成了几个例子,但都失败了。甚至是msdn代码无法为我编译。 有人可以为我提供一个小的工作片段来监视文件并记录
我已经设法让 ReadDirectoryChangesW() 为我需要监视的文件夹工作。我正在使用 IO 完成例程,所有更改监视都是由一个线程完成的,该线程除了等待更改和停止信号外什么都不做。一切都很
我想监控指定目录下的修改,获取准确的修改信息。所以我决定使用 ReadDirectoryChangesW()功能。但我想异步使用它,这意味着如果目录中没有更改,我不希望我的工作线程被阻塞。 我该怎么做
简介: 我正在尝试使用 ReadDirectoryChangesW 在一个循环中异步。 下面的片段说明了我正在努力实现的目标: DWORD example() { DWORD error =
我正在使用 ReadDirectoryChangesW基于此 question 异步观察目录更改我实现了一个监视给定目录的函数,但我仍然收到错误消息 GetQueuedCompletionStatus
我使用下一个代码来了解某个文件夹中的文件何时更改: HANDLE hDir = ::CreateFile(path, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE
我一直在尝试让 ReadDirectoryChangesW 监视子树的文件更改,但我发现我得到的结果不一致。以下是说明问题的自包含测试用例。当我运行它时,它有时会产生: A : Created C :
我已经阅读了 ReadDirectoryChangesW() 的文档,还看到了 CDirectoryChangeWatcher project ,但都没有说明为什么人们想要异步调用它。我知道 curr
我想递归地观察目录中的所有变化,即如果观察 C:\ 我想接收通知 C:\1.txt C:\A\1.txt 如果我使用启用了 watchSubtree 选项的 ReadDirectoryChanges,
我正在使用 GetQueuedCompletionStatusEx() 和 ReadDirectoryChangesW() 尝试接收对多个文件系统层次结构的更改通知。 我注意到当一次有很多更改时,我会
我正在尝试使用 ReadDirectoryChangesW API 使用 python 在 Windows 上查看目录以创建/删除/重命名更改。这是我的代码,它运行良好: results = win3
我将 ReadDirectoryChangesW (Windows API) 与 GetQueuedCompletionStatus 结合使用。如何检测可能的缓冲区溢出以了解至少一个文件系统更改事件已
我有一个应用程序必须监视特定目录中的任何更改。我使用以下代码,但是当我重命名文件时,不会触发操作 FILE_ACTION_RENAMED_NEW_NAME。实际上,触发了 UNDISCOVERED A
我正在尝试使用 ReadDirectoryChangesW 来跟踪文件创建、复制或移动到受监控目录的时间。 我的问题是,当我在受监控的目录上复制或创建文件时,ReadDirectoryChangesW
使用 ReadDirectoryChangesW 监视文件夹会导致其父级被锁定且无法删除。 这里有一篇关于这个的帖子: FindFirstChangeNotification locks parent
这是名为 JNotify 的开源项目的一部分。我正在尝试修复 Win32 实现,这真的让我抓狂。我已经阅读了 MSDN 中关于此的所有内容,并阅读了有关此糟糕 API 的所有网络帖子。我正在尝试使用完
我这样做对吗? 我正在尝试查找在名为 C:\Perl 的文件夹中发生的所有更改 在 ReadDirectoryChangesW 之后,它就卡在那里了。它没有前进。我是否遗漏了一些明显的东西? 我正在努
我调用 ReadDirectoryChangesW异步监视后台线程中的目录更改。 这是如何打开目录 ( basePath) 并启动“读取”线程的: m_hDIR = CreateFileW(
我想在一个线程中实时监控几个目录的变化,所以我决定使用与GetQueuedCompletionStatus异步的ReadDirectoryChangesW()方法。这是我的代码: static DWO
我是一名优秀的程序员,十分优秀!