从运行QML QtQuick2引擎的不同线程更新c++模型的行为

Behaviour of a c++ model update from a different thread from which the QML QtQuick2 engine is running

本文关键字:更新 c++ 模型 线程 QML 运行 QtQuick2 引擎      更新时间:2023-10-16

该场景包含以下组件:

  • c++ QAbstractItemModel在主线程中创建的派生模型类
  • QML QtQuick2引擎在主线程中实例化
  • Worker boost::在用户交互时从主线程生成的线程

组件之间的关系:

    c++模型通过Q_PROPERTY (qmlRegisterSingletonType<>()注册的类型)向QML引擎公开。
  • 工作线程通过调用"emit data_changed(…)"的方法更新模型

问题:在哪个线程的回调"emit data_changed(…)"发生?

注意

这个问题的一个关键因素是已启动的线程不是qt感知的。

我假设工作线程调用某个QObject上的信号方法。这是完全线程安全的,也是一件有效的事情。该信号的实现将当前线程与每个插槽的线程进行比较,并确定使用哪种连接(如果连接是自动类型)。

只要您使用自动或排队连接连接到上述信号,插槽将在其QObject实例的thread()中被调用。

不管信号是在哪个线程中调用的,也不管这个线程是不是Qt线程。

如果你提供一个上下文对象到一个函数函数的连接,这个函数函数将在上下文对象的线程中执行,所以你可以用这种方式对对象进行线程安全的函数函数调用:)

例如:

#include <QtCore>
#include <thread>
class Object : public QObject {
  Q_OBJECT
public:
  Q_SIGNAL void ping();
  Q_SLOT void pong() { 
    qDebug() << "hello on thread" << QThread::currentThread();
    qApp.quit();
  });
};
int main(int argc, char ** argv) {
  QCoreApplication app(argc, argv);
  Object obj;
  qDebug() << "main thread is" << QThread::currentThread();
  QObject::connect(&obj, &Object::ping, &obj, &Object:pong);
  QObject::connect(&obj, &Object::ping, []{
    qDebug() << "context-free functor invoked on thread" << QThread::currentThread();
  });
  QObject::connect(&obj, &QObject::ping, &obj, []{
    qDebug() << "context-ful functor invoked on thread" << QThread::currentThread();
  });
  auto thread = std::thread([&obj]{
    emit obj.ping();
  });
  int rc = app.exec();
  thread.join();
  return rc;
}
#include "main.moc"