我在Qt/c++中开发了一个应用程序,我使用了信号/插槽机制在两个线程之间进行交互。第一个线程运行UI/TreeWidget,第二个线程运行框架
我在一个动作上遇到了问题。
在UI端,在开始我的动作之前,我连接UI和框架之间的信号/槽,如下面的treewidget.cpp
connect(&m_Framework, &Framework::RequestIfNameExist, this, &TreeWidget::RequestIfNameExist);
connect(this, &TreeWidget::SendAnswerIfNameExist, &m_Framework, &Framework::NotifIfNameExist);
框架,启动并发送RequestIfNameExist:
emit RequestIfNameExist(tmpname, item, fileInfo.isDir());
while(WaitingResponse == false){
usleep(200);
}
我添加了一个循环,因为我需要等待反馈。奇怪的是,在treewidget。cpp中,我从来没有输入
void TreeWidget::RequestIfNameExist(QString name, TreeWidgetItem *parent, bool isFolder) {
#ifdef PULS_LOG
QLOG_INFO() << "[TreeWidget] [RequestIfNameExist] ";
#endif
emit SendAnswerIfNameExist(isNameExist(name, parent), isFolder);
}
我从来没有访问过TreeWidget中的RequestIfNameExist,但是信号发出了。
我还在框架中放置了一个while循环,以等待来自TreeWidget的反馈
void Framework::NotifIfNameExist(QTreeWidgetItem *item, bool isFolder){
if(item != NULL)
item->isFolder = isFolder;
WaitingResponse = true;
}
你知道为什么框架发出的信号从来没有到达treewidget吗?它是从一边来的吗?
是否有一种方法可以不使用while,比如"wait event" + timeout
谢谢
我的第一个想法是,让任何一个线程阻塞直到另一个线程中的操作完成是一个糟糕的设计——它在一定程度上违背了使用多个线程的目的,即允许多个操作并行运行。如果不小心,还可能导致死锁(例如,如果两个线程几乎同时决定发出并等待!)
更好的设计是让初始化方法执行emit RequestIfNameExit
,然后立即返回,这样初始化线程的事件循环可以在操作期间继续正常运行。然后,当另一个线程完成它的工作时,它通过发出自己的响应信号来响应,导致调用第一个线程中适当的/已连接的插槽方法,此时在第一个线程中处理返回的结果。
也就是说,如果你坚持想要在一个方法中阻止信号发出线程的执行,直到另一个线程完成执行相关的槽方法,你可以通过将信号/槽连接的类型设置为Qt::BlockingQueuedConnection(连接类型可以通过一个可选的额外参数指定connect())来获得这种行为。如果您这样做,那么emit调用将不会返回,直到槽方法(在另一个线程中)完成执行。考虑到这一点,您可以通过将指向数据对象的指针作为信号/槽方法签名中的参数之一传递给另一个线程来获得结果,并让另一个线程根据需要填充该数据对象。当emit返回时,您只需检查该数据对象的内容即可查看结果。