【发布时间】:2020-07-31 12:36:32
【问题描述】:
您好,我正在将 C++ 与 Qt 框架一起用于 Windows 程序。我使用 Qt 线程,但这种情况也可能与其他线程 API 有关。我正在使用一个工作线程来使用 Win API 中的 ReadDirectoryChangesW 和 WaitForMultipleObjects 来监视目录更改。我希望能够从主线程优雅地取消工作线程。我读过关于 CancellIOEx 的内容,它带有一个句柄和 OVERLAPPED 参数,但这些数据类型都是指针。是否有一些安全的方法可以将这些指针从工作线程安全地传递到主线程?有没有更好的做事方式?
这是来自here 的一些代码,但使用WaitForSingleObject 而不是WaitForMultipleObjects,将从工作线程调用该函数。我可以从链接中发布此代码吗?另请参阅 here,了解有关 Windows 开发中心之外的 ReadDirectoryChangesW 的宝贵信息。
谢谢!
void WatchDirectory(LPCWSTR path)
{
char buf[2048];
DWORD nRet;
BOOL result=TRUE;
char filename[MAX_PATH];
DirInfo[0].hDir = CreateFile (path, GENERIC_READ|FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,
NULL);
if(DirInfo[0].hDir == INVALID_HANDLE_VALUE)
{
return; //cannot open folder
}
lstrcpy( DirInfo[0].lpszDirName, path);
OVERLAPPED PollingOverlap;
FILE_NOTIFY_INFORMATION* pNotify;
int offset;
PollingOverlap.OffsetHigh = 0;
PollingOverlap.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
while(result)
{
result = ReadDirectoryChangesW(
DirInfo[0].hDir,// handle to the directory to be watched
&buf,// pointer to the buffer to receive the read results
sizeof(buf),// length of lpBuffer
TRUE,// flag for monitoring directory or directory tree
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_SIZE,
//FILE_NOTIFY_CHANGE_LAST_WRITE |
//FILE_NOTIFY_CHANGE_LAST_ACCESS |
//FILE_NOTIFY_CHANGE_CREATION,
&nRet,// number of bytes returned
&PollingOverlap,// pointer to structure needed for overlapped I/O
NULL);
WaitForSingleObject(PollingOverlap.hEvent,INFINITE);
offset = 0;
int rename = 0;
char oldName[260];
char newName[260];
do
{
pNotify = (FILE_NOTIFY_INFORMATION*)((char*)buf + offset);
strcpy(filename, "");
int filenamelen = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength/2, filename, sizeof(filename), NULL, NULL);
filename[pNotify->FileNameLength/2] = '';
switch(pNotify->Action)
{
case FILE_ACTION_ADDED:
printf("\nThe file is added to the directory: [%s] \n", filename);
break;
case FILE_ACTION_REMOVED:
printf("\nThe file is removed from the directory: [%s] \n", filename);
break;
case FILE_ACTION_MODIFIED:
printf("\nThe file is modified. This can be a change in the time stamp or attributes: [%s]\n", filename);
break;
case FILE_ACTION_RENAMED_OLD_NAME:
printf("\nThe file was renamed and this is the old name: [%s]\n", filename);
break;
case FILE_ACTION_RENAMED_NEW_NAME:
printf("\nThe file was renamed and this is the new name: [%s]\n", filename);
break;
default:
printf("\nDefault error.\n");
break;
}
offset += pNotify->NextEntryOffset;
}while(pNotify->NextEntryOffset); //(offset != 0);
}
CloseHandle( DirInfo[0].hDir );
}
【问题讨论】:
-
将event object 添加到您正在等待的句柄数组中,并在您希望工作线程终止时发出该事件的信号。
-
谢谢,幸运的是,这是非常简单的东西:) 有没有关于这类事情的书或一些信息来源? Win API 有时可能有点难以捉摸......
-
您只需要 2 本书即可快速掌握 Windows API:Charles Petzold 的 Programming Windows®, Fifth Edition 解释了应用程序开发的基本要素。它已经过时了,但几乎所有内容在今天仍然适用。对于系统编程,有 Jeffrey Richter 的Advanced Windows。这就是我所拥有的,但有一份修订后的出版物 (Windows via C/C++) 说明了操作系统的变化。你可能想要后者。
-
@IInspectable Event 对象有一个小问题。我从主线程创建事件,然后从工作线程打开事件。我得到 OpenEvent failed with error 5: Access is denied in the worker thread。默认安全描述符不应该足够吗?我做错了什么?
-
想我明白了...关键部分是 EVENT_ALL_ACCESS OpenEvent(EVENT_ALL_ACCESS,FALSE,TEXT("MainEvent"));
标签: c++ multithreading qt winapi