c++ - QEventLoop 用于同步等待信号

标签 c++ multithreading qt

我正在使用 Qt5、QCoreApplication。 为了使代码可读且易于维护,我需要在类/线程 A 中编写一个阻塞方法,该方法将发出信号,连接到不同线程 B 中的插槽,然后等待应答或超时在线程 B 中异步发生。 我首先考虑的是一个自然的解决方案:让线程 B 用连接到线程 A 中的插槽的信号进行回复,并以某种方式等待它。看来 QEventLoop 可以为我做到这一点。但我一直在阅读矛盾的陈述:这就是模式,但如果可以的话,请避免它:-)。 我很确定我可以通过在 0 QSemaphore 上阻止 A 来实现我的目的,而 B 在准备好时会释放该 QSemaphore。这样代码可能不会更复杂。 经验丰富的 Qt 开发人员有何看法? 有没有一个好的解决方案,或者您在我的描述中发现了一些有缺陷的分析症状(即您认为我永远不需要做这样的事情吗?:-))?

最佳答案

您可以利用的关键要素是Qt::BlockingQueuedConnection

此连接类型允许您传递槽的返回值。您可以在信号槽连接中使用它。您还可以通过 QMetaMethod::invoke/QMetaObject::invokeMethod 机制直接调用插槽,而无需使用信号。

#include <QDebug>
#include <QThread>
#include <QCoreApplication>

class Master : public QObject {
  Q_OBJECT
public:
  Q_SIGNAL bool mySignal();
  Q_SLOT void process() {
    if (mySignal()) { // this can be a blocking call
      qDebug() << "success!";
    }
    thread()->quit();
  }
};

class Slave : public QObject {
  Q_OBJECT
public:
  Q_SLOT bool mySlot() {
    // do whatever processing is needed here
    // It's OK to call QCoreApplication::processEvents here
    return true;
  }
};

int main(int argc, char** argv) {
  QCoreApplication app(argc, argv);
  QThread masterThread, slaveThread;
  Master master;
  Slave slave;
  master.moveToThread(&masterThread);
  slave.moveToThread(&slaveThread);
  slave.connect(&master, SIGNAL(mySignal()), SLOT(mySlot()),
                Qt::BlockingQueuedConnection);
  masterThread.start();
  slaveThread.start();
  QMetaObject::invokeMethod(&master, "process");
  masterThread.wait();
  slaveThread.quit();
  slaveThread.wait();
  return 0;
}

#include "main.moc"

关于c++ - QEventLoop 用于同步等待信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21416487/

相关文章:

ios - `SCNetworkReachabilityScheduleWithRunLoop` 还是 `SCNetworkReachabilitySetDispatchQueue`?和比赛条件

qt - QQuickView,切换窗口后没有键盘焦点

c++ - QPlainTextEdit - setViewportMargins, protected

c++ - 线程间通信。如何向另一个线程发送信号

android - 音频 seekBar 线程问题?

c++ - 修改XML文件QXMLStreamReader/Writer

c++ - 在 OpenGL : Will not make Blank Screen (Makes infinite copies instead) 中打开一个窗口

c++ - 插入时调用 std::map 值对象的成员函数

c++ - 每次调用 CryptSignMessage() 时都需要密码

c++ - 如何重用相同的顶点着色器来绘制不同的 gl_Position