Qt / C ++当信号发出时如何等待插槽

时间:2015-06-04 01:36:27

标签: c++ multithreading qt5 signals-slots

我在Qt / C ++中开发了一个应用程序,我使用信号/插槽机制在2个线程之间进行交互。第一个线程运行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?它来自何时??

有没有办法不使用,例如“等待事件”+超时

由于

1 个答案:

答案 0 :(得分:4)

我的第一个想法是,在另一个线程中的操作完成之前使用任一线程阻塞是一个糟糕的设计 - 它部分地违背了拥有多个线程的目的,这允许多个操作并行运行。如果您不小心(例如,如果两个线程决定在大约同一时间发出并等待!),它也可能导致死锁。

更好的设计会使启动方法执行emit RequestIfNameExit然后立即返回,以便启动线程的事件循环可以在操作期间照常继续运行。然后,当另一个线程完成其工作时,它通过发出自己的响应信号来响应,导致第一个线程中的相应/连接的slot方法被调用,此时结果在第一个线程中被处理回来。

那就是说,如果你坚持想要阻止方法中的信号发送线程的执行,直到另一个线程完成执行相关的slot-method,你可以通过设置信号/槽连接来获得该行为#39; s类型为Qt::BlockingQueuedConnection(连接类型可以通过connect()的可选额外参数指定)。如果你这样做,那么你发出的调用不会返回,直到slot-method(在另一个线程中)完成执行。鉴于此,您可以通过将指针作为信号/槽方法签名中的参数之一传递给数据对象来获取其他线程的结果,并让其他线程根据需要填充该数据对象。当emit返回时,您可以检查该数据对象的内容以查看结果。