具有多个线程的 QML C++ 属性绑定

qml c++ property bindings with multiple threads

本文关键字:QML C++ 属性 绑定 线程      更新时间:2023-10-16

我正在创建一个模块化应用程序。它有一个Core,和几个模块,其中一个是gui模块。这些模块可以通过命令行启动:

myApp gui=qml=qmlFile.qml connection=serial=/dev/ttyS1

将使用一个(也可以多个(GUI和一个串行连接启动应用程序。始终有一个Router对象来处理连接。Guis 由如下所示的类加载:

class Gui :QObject{
  Core* core;
  public:
  QQmlApplicationEngine engine;
  public slots:
  void start(){
    engine.load("qrc:/gui/from/command/line.qml");
  }

在 gui 中,我有一个名为 ConnectionController{} 的 qml,这是一种添加/删除连接的简单方法。但这只是同类产品中的第一次:最终每个模块都应该有一个 qml 组件来控制它。

这一切都工作正常,但现在我正在尝试添加多个线程。我想有一个RouterThread和一个GuiThread.这本身只是将Router(由Core(的创建更改为以下问题:

m_router = new Router(this /*not as parent, just as pointer*/);
m_router->moveToThread(&routerThread);

(GUI目前仍存在于主线程中(在此之后,除了 qml 属性绑定之外,一切仍然正常工作。

QQmlEngine: Illegal attempt to connect to SerialConnection(0x7f58d00013a0) that is in a different thread than the QML engine

因为Gui和孩子QQmlEngine engine住在guiThread,而SerialConnection住在routerThread
RouterGui之间的信号和插槽(没有qml(确实有效,因为它们默认由qt作为异步处理(只要定义了适当的类型(。

嗯,不,你不能从你的 gui 访问线程对象,也不应该尝试。

您需要构建一个位于向 qml 公开的主线程中的 c++ 模型。在此模型中,您可以通过队列连接连接到线程发出的信号,并将它们链接到模型自己的信号。此外,您应该确保当您从另一个线程拥有的对象读取数据时,所有内容都正确互斥,否则您将读取垃圾。