Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

qml c++ property bindings with multiple threads

I am creating an modular application. It has a Core, and a few modules, amongs which is a gui module. These modules can be started via the command line:

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

will start the app with one (multiple is also possible) gui and one serial connection. There is always one Router object, which handles the connection. Guis are loaded by a class that looks like this:

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

In the gui i have a nice bit of qml called ConnectionController{} which is an easy way of adding/removing connections. But this is only the first of it's kind: in the end every module should have a qml component for controlling it.

This all works fine, but now i am trying to add multiple threads. I want to have a RouterThread and a GuiThread. This in itself was simply a matter of changing the creation of the Router (by the Core) to this:

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

(gui's still live in the main thread for now) After this everything still works fine, except for qml property bindings.

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

Because Gui and it's child QQmlEngine engine live in the guiThread while the SerialConnection lives in the routerThread.
Signals and slots between Router and Gui (without qml) do work, because they are handled by default as asynchronous by qt. (as long as the appropriate types are defined.)

like image 570
David van rijn Avatar asked Sep 27 '22 07:09

David van rijn


1 Answers

Well, no, you cant access threaded objects from your gui and should not try to either.

You need to build a c++ model that lives in the main thread that is exposed to qml. Inside this model you can connect to signals emitted by your threads via a queuedconnection and link them to the models' own signals. Also you should make sure that when you read data from an object owned by another thread, everything is properly mutexed or you will be reading garbage.

like image 195
Teimpz Avatar answered Sep 29 '22 07:09

Teimpz