从线程更改状态栏文本时程序崩溃

时间:2014-05-17 13:43:03

标签: c++ multithreading qt winapi

我正在使用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进行线程化。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

  

要更改QLabel文本,我将指针传递给它作为在线程中运行的函数的参数。

这就是问题所在。您不能直接操作除主线程(调用QApplication::exec()的线程)之外的任何线程的QWidgets。

根据Qt documentation

  

GUI类,尤其是QWidget及其所有子类,不是可重入的。它们只能在主线程中使用。

理想的解决方案是重新编写程序,使工作线程为QThreads,并使用Qt的信号和插槽机制自动处理线程间通信和同步。

如果您不能使用QThreads,则必须设置自己的线程间通信。一种方法是使用互斥锁保护的共享队列。工作线程会将项目推入其中,GUI线程会偶尔轮询它。