【发布时间】:2011-05-27 10:29:58
【问题描述】:
正如听起来一样,我正在尝试使用 IO Completion 进行异步 ReadDirectoryChangesW,但它不起作用,具体来说,GetLastError 反复返回 258(GetQueuedCompletionStatus 超时)。
我有结构:
typedef struct dirinfo_struct
{
HANDLE hDirFH; // directory handle
OVERLAPPED Overlapped; // overlapped storage
int len_buffer; // buffer length
wchar_t* buffer; // buffer itself
wchar_t* directory_name; // target name
} dirinfo_t;
typedef struct dirmon_struct
{
HANDLE hDirOPPort; // handle to the IO port.
dirinfo_t* dirinfo; // pointer to the struct above.
} dirmon_t;
用于存储相关信息。这是初始化的:
dirinfo_t* t = malloc(1*sizeof(dirinfo_t));
dirmon_t* d = malloc(1*sizeof(dirmon_t));
dirinfo_init(t); // does t->buffer = malloc(8192*sizeof(wchar_t));
然后我创建我的目录句柄和 com 端口:
t->hDirFH = CreateFile(L"C:\\test",
FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
d->dirinfo = t;
d->hDirOPPort = CreateIoCompletionPort(d->dirinfo->hDirFH,
NULL,
(ULONG_PTR)(d->dirinfo),
1);
然后我通过 d 将此信息传递给一个新线程。现在在我说的新线程上:
bResultQ = GetQueuedCompletionStatus(d->hDirOPPort, lpBytes,
(ULONG_PTR*)d->dirinfo,
lpOverlapped, 1000);
if ( bResultQ )
{
bResultR = ReadDirectoryChangesW(d->dirinfo->hDirFH,
(void*)d->dirinfo->buffer,
8192, TRUE,
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 |
FILE_NOTIFY_CHANGE_SECURITY,
lpReadDirBytes,
&d->dirinfo->Overlapped,
NULL );
}
else
{
printf("GetQueuedCompletionStatus(): Failed, ");
errorcode = GetLastError();
printf("Error Code %d\n", errorcode);
Sleep(500);
}
因此,我将其设置为运行状态,并且由于目录没有更改,因此我很高兴地得到了超时(258 个错误)。但是,即使我更改了目录,我仍然会收到错误消息;换句话说,这些改动没有被采纳。这让我相信我的设置不正确。
有什么想法吗?
注意事项:
- 具有讽刺意味的是,这最终将通过 pywin32 转换为 Python。但是,在我了解这在 C 中应该如何工作之前,我不会去那里。
- 同步
ReadDirectoryChangesW不是一个选项。如果没有触发任何事件,我需要这个线程超时,以便它可以检查它是否应该仍在运行。 - 我是专门用 C 编写的,而不是 C++。
-
FindFirstChangeNotification等也不是一个选项 - 我不想不断比较目录列表来找出发生了什么变化。
其他说明:
- 目录存在,句柄不为 NULL。对于 comport 句柄也是如此。
- 一切都被传递给线程
我从代码项目中查看了CDirectoryChangeWatcher,但是除了使用 C++ 和更多线程之外,我看不出我在做什么不同。如果我遗漏了什么,请随时指出!
输出,如果有帮助的话,基本上是重复的,不管我如何改变有问题的目录。
GetQueuedCompletionStatus(): Failed, Error Code 258
【问题讨论】:
-
让它正常工作并非易事(委婉地说)。如果您还没有,我建议您阅读 Jim Beveridge 的博客:qualapps.blogspot.com/2010/05/…。警告:他的示例代码是用 C++ 编写的,但至少比大多数代码要好。警告2:我有理由确定,无论您做什么,ReadDirectoryChangesW 都不会真正完全正确地工作。我通常建议改用更改日志。 msdn.microsoft.com/en-us/library/aa363798.aspx。它们也不是微不足道的,但至少它们确实有效。
-
@Jeffy 谢谢,我查看了他的来源,但他没有(据我所知)使用 GetQueue... 或 CreateIo... 他的自述文件暗示了比实际更多的文件实际上在那里,所以我认为他已经删除了它们。我慢慢开始意识到这一点......不幸的是,更改期刊需要我们可能没有的管理员权限。我总是可以启动一个 Windows 服务来处理我想的。
标签: c winapi asynchronous readdirectorychangesw