我正在使用Qt进行接口,使用winAPI进行线程化并索引所有硬盘上的所有文件。我有一个状态栏,QLabel显示当前正在索引的目录。要更改QLabel文本,我将指针传递给它作为在线程中运行的函数的参数。程序在更改QLabel文本时崩溃,但如果在不更改QLabel文本的情况下运行它会正常执行。调试器在以下
的最后一行停止 Function: ntdll!RtlpSetUserPreferredUILanguages
0x77d656a9 <+0x38ae> add (%eax),%al
0x77d656ab <+0x38b0> je 0x77d656c4
<ntdll!RtlpSetUserPreferredUILanguages+14537>
0x77d656ad <+0x38b2> mov 0x8(%ebp),%eax
0x77d656b0 <+0x38b5> movb $0x1,0x77d7f0a5
0x77d656b7 <+0x38bc> mov %eax,0x77d7f0a0
0x77d656bc <+0x38c1> int3
0x77d656bd <+0x38c2> movb $0x0,0x77d7f0a5
在线程中运行的函数
uintptr_t __stdcall threadFunction(void* labelPtr)
{
for(std::list<std::wstring>::iterator i = discLetters.begin(); i != discLetters.end(); ++i)
{
findAllFilesInDirectory((*i).c_str(), filesData, (QLabel*)labelPtr);
}
Serializer<std::list<FileInfo>> xmlFile("D:\\res.xml");
xmlFile.serialize(filesData);
}
创建线程
threadHandle = _beginthreadex(NULL, 0, &threadFunction, (void*)(ui->currentDirectoryLabel), NULL, NULL);
我被迫使用WinAPI进行线程化。有人可以帮忙吗?
答案 0 :(得分:1)
要更改QLabel文本,我将指针传递给它作为在线程中运行的函数的参数。
这就是问题所在。您不能直接操作除主线程(调用QApplication::exec()
的线程)之外的任何线程的QWidgets。
GUI类,尤其是QWidget及其所有子类,不是可重入的。它们只能在主线程中使用。
理想的解决方案是重新编写程序,使工作线程为QThreads,并使用Qt的信号和插槽机制自动处理线程间通信和同步。
如果您不能使用QThreads,则必须设置自己的线程间通信。一种方法是使用互斥锁保护的共享队列。工作线程会将项目推入其中,GUI线程会偶尔轮询它。