[英]How to keep std::thread from freezing GUI in QT?
我正在一个项目中,我将提取多个二进制文件,对其进行解码,然后将其数据转换为CSV。 我认为最快的方法是将工作线程化。 只需将文件加载到队列中,让线程抓取一个文件,对其进行处理,对其进行转换,将其输出然后消失。
实际上,我写的东西效果很好,但是我无法弄清楚如何使GUI响应,因为我有一个要更新的进度条,或者只是让用户在处理数据时将其移至角落。 我相信这是因为std::thread
只是挂断了GUI。
在我的代码中,一旦按下按钮即可执行以下功能:
void MyExtractor::on_Execute_clicked()
{
QStringList binary = tlmFiles.entryList(QStringList() << "*.bin",QDir::Files);
queue.clear();
threadPool.clear();
if(binary.size() != 0)
{
foreach(QString filename, binary)
{
queue.emplace_back(inputDir + '/' + filename);
}
for (unsigned int i = 0; i < std::thread::hardware_concurrency(); ++i)
{
threadPool.emplace_back(&MyExtractor::initThread,this,std::ref(queue),std::ref(mut));
}
}
else
{
message.setText("No binary files found! Please select another folder!");
message.exec();
}
for (auto &&e : threadPool)
{
e.join();
}
}
initThread看起来像这样:
void MyExtractor::initThread(std::deque<QString> &queue, std::mutex &mutex)
{
QString file;
QString toOutput = outputDir;
while(queue.size() > 0)
{
{
std::lock_guard<std::mutex> lock(mutex);
if(!queue.empty())
{
file = queue.front();
queue.pop_front();
}
}
BitExtract *bitExtractor = new BitExtract();
if(file.size() != 0)
{
bitExtractor->extract(file,toOutput);
}
delete bitExtractor;
}
}
我一直在阅读有关QThreads的文章。 从我想我一直在阅读的内容来看,似乎需要创建一个单独的线程来监视工作,而另一个线程来监视GUI? 我不确定我的措词是否正确。 但是,由于使用std::thread
进行转换,因此我什至不知道如何执行此操作,而且我不确定QThread
将如何处理此问题。 有什么建议么?
编辑:我应该明确指出threadPool
是std::vector<std::thread>
如@drescherjm所述,您的问题在这里:
for (auto &&e : threadPool)
{
e.join();
}
join()
在线程完成之前不会返回,这意味着您的GUI线程将在该for循环内被阻塞,直到所有线程都退出为止,这是您要避免的事情。 (总是希望主/ Qt / GUI线程中的任何函数尽快返回,以便Qt的GUI事件循环可以保持响应)
避免是相当简单的-而不是调用join()
的线程已经催生了之后,你应该只调用join()
上的线程的线程已经通知你之后,该公司已经完成其工作,即将退出。 这样, join()
绝不会花费几毫秒的时间就可以返回。
至于如何获取std::thread
来通知您的主/ GUI线程其任务已完成,一种简单的方法是在退出前,让您的std::thread
调用QApplication :: postEvent() ,并覆盖(无论您作为postEvent()的第一个参数传入的任何对象)上的event(QEvent *)虚拟方法,以处理所发布的事件对象(请注意,您可以使自己的QEvent
子类包含所需的任何数据)发送到GUI线程),方法是在std::thread
上调用join()
,再加上线程返回结果后需要执行的任何清理和结果处理代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.