【发布时间】:2018-09-09 21:30:45
【问题描述】:
我的多线程代码有问题,希望有人能帮助我。
我希望在控制台上打印从作为参数给出的文件夹开始的所有文件和文件夹。我使用这个函数进行枚举:
void enumerate(char* path) {
HANDLE hFind;
WIN32_FIND_DATA data;
char *fullpath = new char[strlen(path) - 1];
strcpy(fullpath, path);
fullpath[strlen(fullpath) - 1] = '\0';
hFind = FindFirstFile(path, &data);
do {
if (hFind != INVALID_HANDLE_VALUE) {
if (strcmp(data.cFileName, ".") != 0 && strcmp(data.cFileName, ".."))
{
EnterCriticalSection(&crit);
queue.push(data.cFileName);
LeaveCriticalSection(&crit);
ReleaseSemaphore(semaphore, 1, NULL);
if (data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
strcat(fullpath, data.cFileName);
strcat(fullpath, "\\*");
enumerate(fullpath);
}
}
}
} while (FindNextFile(hFind, &data));
FindClose(hFind);
return;
}
当我找到一个文件或文件夹时,我想将它添加到一个全局队列并让我的工作线程将它打印到控制台。我的工作线程函数是:
DWORD WINAPI print_queue(LPVOID param) {
while (1) {
WaitForSingleObject(semaphore, INFINITE);
EnterCriticalSection(&crit);
char *rez = queue.front();
queue.pop();
LeaveCriticalSection(&crit);
if (strcmp(rez, "DONE") == 0)
break;
else
std::cout << rez << std::endl;
}
return 1;
}
在main 中,我初始化信号量和临界区,这两个变量都是全局声明的:
semaphore = CreateSemaphore(NULL, 0,1, NULL);
InitializeCriticalSection(&crit);
然后创建4个线程:
thread1 = CreateThread(NULL, 0, print_queue, NULL, 0, &tId1);
thread2 = CreateThread(NULL, 0, print_queue, NULL, 0, &tId2);
thread3 = CreateThread(NULL, 0, print_queue, NULL, 0, &tId3);
thread4 = CreateThread(NULL, 0, print_queue, NULL, 0, &tId4);
然后我调用 enumerate() 函数并将字符串放入队列中,当达到这些字符串时,我的线程将停止:
for (int p = 0; p<4; p++)
{
EnterCriticalSection(&crit);
queue.push(done);
LeaveCriticalSection(&crit);
ReleaseSemaphore(semaphore, 1, NULL);
}
这 4 个字符串是我的线程的停止条件。然后我等待线程:
HANDLE * threadArray = new HANDLE[4];
threadArray[0] = thread1;
threadArray[1] = thread2;
threadArray[2] = thread3;
threadArray[3] = thread4;
WaitForMultipleObjects(4, threadArray, TRUE, INFINITE);
并关闭信号量和临界区:
CloseHandle(semaphore);
DeleteCriticalSection(&crit);
由于某种原因,输出是随机垃圾,我不知道为什么。
这是一个示例输出:
te(L┤(L ┤(L ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ / ╠╠╠╠╠我的逻辑是从 0 开始信号量,每当队列上发生操作以保护我的数据时进入临界区,在 enumerate() 函数中增加信号量并在 print_queue() 中减少它。
可能是什么问题?
【问题讨论】:
-
队列的声明是什么样子的?
-
我强烈建议放弃 STL 的 winapi 内容 --
std::mutex、conditon_variable、async、queue... 至少,将 CRITICAL_SECTION 包装在 RAII 类中. -
文件夹不仅可以包含
FILE_ATTRIBUTE_DIRECTORY属性集。请改用if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)。 -
为什么你不使用内置的 Windows 队列实现 - iocp - 有了这个你就不需要任何关键部分、信号量等。
-
与您的代码的大量问题无关,我不相信在此设置中使用工作线程会给您带来任何开销。
标签: c++ multithreading winapi semaphore critical-section