【问题标题】:Difference between Qt::QueuedConnection and Qt::DirectConnection when connecting a signal to a lambda将信号连接到 lambda 时 Qt::QueuedConnection 和 Qt::DirectConnection 之间的区别
【发布时间】:2021-02-15 15:41:03
【问题描述】:

让我们考虑两个QObjectssenderObject 类型为SenderObjectreceiverObject 类型为ReceiverObject 的场景。 senderObject 已在工作线程上创建,而 receiverObject 已在主线程上创建。现在让我们假设SenderObject 有一个信号somethingsChanged,让我们考虑下面的代码sn-p:

片段1:

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  QThread t;
  SenderObject senderObject = new SenderObject();
  senderObject.moveToThread(&t);
  ReceiverObject receiverObject = new ReceiverObject();
  //in this case we know for a fact that receiverObject's 
  //onSomethingsChanged() will be called on the main thread
  QObject::connect(senderObject, &SenderObject::somethingsChanged, 
  receiverObject, &ReceiverObject::onSomethingsChanged, Qt::QueuedConnection);
  t.start();
  return a.exec();
}

现在让我们考虑以下代码 sn-p:

片段2:

int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  QThread t;
  SenderObject senderObject = new SenderObject();
  senderObject.moveToThread(&t);
  //where will qDebug() << "Hello, world" be executed? 
  //On the main thread again since the lambda lives on the main thread?
  QObject::connect(senderObject, &SenderObject::somethingsChanged, 
  []{qDebug << "Hello, world";});
  t.start();
  return a.exec();
}

由于 lambda 已在主线程上声明,Snippet2 中的 lambda 是否也会在主线程上执行,还是会在与 senderObject 相同的线程中执行?

【问题讨论】:

    标签: c++ multithreading qt qwidget qthread


    【解决方案1】:

    这是我们的课程SenderObject:

    class Sender : public QObject {
      Q_OBJECT
     public:
      explicit Sender() : QObject() {
        _timer.setInterval(1000);
        connect(&_timer, &QTimer::timeout, this,
                [this] { emit somethingsChanged(); });
        _timer.start();
      }
    
     signals:
      void somethingsChanged();
    
     private:
      QTimer _timer;
    };
    

    由于没有QObject::connect 的重载将采用 lambda 和 Qt 连接类型参数,因此 Snippet2 将在发送者的线程中执行,这是一个工作线程。

    为了强制 lambda 在主线程上执行,这里有一个解决方法:

    int main(int argc, char *argv[]) {
      QCoreApplication a(argc, argv);
      QThread t;
      SenderObject senderObject = new SenderObject();
      senderObject.moveToThread(&t);
      QObject::connect(senderObject, &SenderObject::somethingsChanged, new QObject,
      []{qDebug << "Hello, world";}, Qt::QueuedConnection);
      t.start();
      return a.exec();
    }
    

    由于在主线程上调用了new QObject,因此 lambda 也将在主线程上执行。

    或者,如果我们不喜欢看到new,这将是可行的:

    int main(int argc, char *argv[]) {
      QCoreApplication a(argc, argv);
      QThread t;
      SenderObject senderObject = new SenderObject();
      senderObject.moveToThread(&t);
      QObject object;
      QObject::connect(senderObject, &SenderObject::somethingsChanged, &object,
      []{qDebug << "Hello, world";}, Qt::QueuedConnection);
      t.start();
      return a.exec();
    }
    

    或者,甚至更好的解决方案是使用qApp,它是应用程序的一个实例和一个单例,可在任何地方使用。

    int main(int argc, char *argv[]) {
      QCoreApplication a(argc, argv);
      QThread t;
      SenderObject senderObject = new SenderObject();
      senderObject.moveToThread(&t);
      QObject::connect(senderObject, &SenderObject::somethingsChanged, qApp,
      []{qDebug << "Hello, world";}, Qt::QueuedConnection);
      t.start();
      return a.exec();
    }
    

    【讨论】:

      猜你喜欢
      • 2013-02-09
      • 2011-02-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      相关资源
      最近更新 更多