简体   繁体   English

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

[英]Qt/C++ how to wait a slot when signal emitted

I have developed an app in Qt/C++, I have used signal/slot mechanism to interact between 2 threads. 我已经用Qt / C ++开发了一个应用程序,我已经使用信号/插槽机制在2个线程之间进行交互。 the first thread run the UI/TreeWidget and the second one run the framework 第一个线程运行UI / TreeWidget,第二个线程运行框架

I got an issue on one action. 我在一个动作上遇到了问题。

In the UI side, before starting my action, I'm connect signal/slot between UI and framework such as below in the treewidget.cpp 在UI端,在开始操作之前,我要在UI和框架之间连接信号/插槽,例如以下treewidget.cpp

connect(&m_Framework, &Framework::RequestIfNameExist, this, &TreeWidget::RequestIfNameExist);
connect(this, &TreeWidget::SendAnswerIfNameExist, &m_Framework, &Framework::NotifIfNameExist);

The framework, start and send the RequestIfNameExist: 框架,启动并发送RequestIfNameExist:

emit RequestIfNameExist(tmpname, item, fileInfo.isDir());

while(WaitingResponse == false){
    usleep(200);
}

I have added a loop because I need to wait the feedback. 我添加了一个循环,因为我需要等待反馈。 Strange things is that in the treewidget.cpp, I never enter in 奇怪的是,在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);
}

I never access to RequestIfNameExist in the TreeWidget but the signal is emitted. 我从不访问TreeWidget中的RequestIfNameExist,但是发出了信号。

I have also put a while loop in the framework to wait the feedback from TreeWidget 我还在框架中放置了一个while循环,以等待TreeWidget的反馈

void Framework::NotifIfNameExist(QTreeWidgetItem *item, bool isFolder){

    if(item != NULL)
        item->isFolder = isFolder;

    WaitingResponse = true;

}

Any idea why the signal emitted by framework never arrived on the treewidget ? 知道为什么框架发出的信号从未到达树部件吗? is it coming from the while ?? 是一阵子来的吗?

Is there a way to not use while such as a "wait event" + timeout 有没有一种方法可以不使用,例如“等待事件” +超时

Thanks 谢谢

My first thought is that having either thread block until an operation in the other thread completes is a poor design -- it partially defeats the purpose of having multiple threads, which is to allow multiple operations to run in parallel. 我的第一个想法是,只有一个线程阻塞直到另一个线程中的一个操作完成才是一个糟糕的设计,这部分地抵消了拥有多个线程的目的,后者允许多个操作并行运行。 It's also liable to result in deadlocks if you're not careful (eg if both threads decide to emit-and-wait at approximately the same time!) 如果您不小心,还可能导致死锁(例如,如果两个线程都决定大约在同一时间发出并等待!)

A better design would have the initiating method do the emit RequestIfNameExit and then return immediately, so that the initiating thread's event loop can continue running as usual during the operation. 更好的设计是让发起方方法emit RequestIfNameExit ,然后立即返回,以便发起方线程的事件循环可以在操作期间像往常一样继续运行。 Then, when the other thread has done its work, it responds by emitting its own response-signal, causing the appropriate/connected slot-method in the first thread to be called, at which point the results are handled back in the first thread. 然后,当另一个线程完成其工作时,它将通过发出自己的响应信号进行响应,从而导致在第一个线程中调用适当/已连接的插槽方法,这时将在第一个线程中处理结果。

That said, if you insist on wanting to block the execution of the signal-emitting thread inside a method, until the other thread has finished executing the associated slot-method, you can get that behavior by setting the signal/slot connection's type to be Qt::BlockingQueuedConnection (the connection type can be specified via an optional extra argument to connect() ). 也就是说,如果您坚持要阻止某个方法中信号发射线程的执行,直到另一个线程完成了相关的插槽方法的执行,您可以通过将信号/插槽连接的类型设置为来获得该行为。 Qt :: BlockingQueuedConnection (可以通过connect()的可选附加参数指定连接类型)。 If you do that, then you emit call won't return until the slot-method (in the other thread) has finished executing. 如果这样做,则直到插槽方法(在另一个线程中)执行完后,您的发出调用才会返回。 Given that, you can get the results from the other thread by passing a pointer to a data object as one of the arguments in the signal/slot method signature, and having the other thread populate that data object as necessary. 鉴于此,您可以通过将一个指针作为信号/插槽方法签名中的参数之一传递给数据对象,并根据需要让另一个线程填充该数据对象,从而从另一个线程获得结果。 When the emit returns you can just examine the contents of that data object to see the results. 当发射返回时,您可以仅检查该数据对象的内容以查看结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM