Qt/C++ 信号发出时如何等待槽
Qt/C++ how to wait a slot when signal emitted
我在Qt/C++中开发了一个应用程序,我使用了signal/slot机制在2个线程之间进行交互。第一个线程 运行 UI/TreeWidget 第二个 运行 框架
我在一项操作上遇到了问题。
在UI方面,在开始我的行动之前,我在UI和treewidget.cpp[=15=下面的框架之间连接signal/slot ]
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
然后 return,这样启动线程的事件循环可以在操作期间像往常一样继续 运行ning。然后,当另一个线程完成它的工作时,它通过发出自己的响应信号来响应,导致第一个线程中的 appropriate/connected 槽方法被调用,此时结果在第一个线程中处理回来线程。
就是说,如果您坚持要在一个方法内阻止信号发射线程的执行,直到另一个线程完成关联的插槽方法的执行,您可以通过设置 signal/slot 连接类型为 Qt::BlockingQueuedConnection (the connection type can be specified via an optional extra argument to connect())。如果你这样做,那么在插槽方法(在另一个线程中)完成执行之前,你不会发出调用 return 。鉴于此,您可以通过将指向数据对象的指针作为 signal/slot 方法签名中的参数之一传递并让另一个线程根据需要填充该数据对象来从另一个线程获取结果。当发出 returns 时,您可以检查该数据对象的内容以查看结果。
我在Qt/C++中开发了一个应用程序,我使用了signal/slot机制在2个线程之间进行交互。第一个线程 运行 UI/TreeWidget 第二个 运行 框架
我在一项操作上遇到了问题。
在UI方面,在开始我的行动之前,我在UI和treewidget.cpp[=15=下面的框架之间连接signal/slot ]
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
然后 return,这样启动线程的事件循环可以在操作期间像往常一样继续 运行ning。然后,当另一个线程完成它的工作时,它通过发出自己的响应信号来响应,导致第一个线程中的 appropriate/connected 槽方法被调用,此时结果在第一个线程中处理回来线程。
就是说,如果您坚持要在一个方法内阻止信号发射线程的执行,直到另一个线程完成关联的插槽方法的执行,您可以通过设置 signal/slot 连接类型为 Qt::BlockingQueuedConnection (the connection type can be specified via an optional extra argument to connect())。如果你这样做,那么在插槽方法(在另一个线程中)完成执行之前,你不会发出调用 return 。鉴于此,您可以通过将指向数据对象的指针作为 signal/slot 方法签名中的参数之一传递并让另一个线程根据需要填充该数据对象来从另一个线程获取结果。当发出 returns 时,您可以检查该数据对象的内容以查看结果。