Sync objects properties in different threads to display in QML
-
Hello everyone!
I have a slightly conceptual question: what is the best practice to sync objects properties in different threads? I have a QML interface and C++ QObject in the same thread (an 'interface'). This C++ object manage QThread and C++ QObject in it (business logic, 'implementation'). So I need to send commands from GUI to business logic and receive all changes. Does the common practice exist? What I have done at this moment:
- 'implementation' has a
Q_PROPERTY
with all necessary members/getters/setters/signals. - 'interface' has
Q_PROPERTY
but without a field (to prevent memory usage duplication) - 'interface' methods get/set use
QMetaObject::invokeMethod
(Qt::BlockingQueuedConnection
andQt::QueuedConnection
appropriately). - 'interface' <...>Changed() signal is just connected to 'implementation' <...>Changed()
- QML uses 'interface' binding:
active: connection.connected
Everything works well, but when the changes comes to GUI, the main thread hangs if 'implementation' thread continues to do something. I can see changes while using
Connections { target: connection function onConnectedChanged(inProgress) { console.log("connected", connected); } }
But if the 5 step (property binging) is used, gui stucks. I think the reason is QML re-requesting, using getter with invokeMethond and some kind of an deadlock as a result.
So does other common practice exist to do so (if I'm doing it wrong)? Or maybe memory duplication can solve the issue (with not so sufficient memory usage (bools, ints and so on)
- 'implementation' has a
-
Hello everyone!
I have a slightly conceptual question: what is the best practice to sync objects properties in different threads? I have a QML interface and C++ QObject in the same thread (an 'interface'). This C++ object manage QThread and C++ QObject in it (business logic, 'implementation'). So I need to send commands from GUI to business logic and receive all changes. Does the common practice exist? What I have done at this moment:
- 'implementation' has a
Q_PROPERTY
with all necessary members/getters/setters/signals. - 'interface' has
Q_PROPERTY
but without a field (to prevent memory usage duplication) - 'interface' methods get/set use
QMetaObject::invokeMethod
(Qt::BlockingQueuedConnection
andQt::QueuedConnection
appropriately). - 'interface' <...>Changed() signal is just connected to 'implementation' <...>Changed()
- QML uses 'interface' binding:
active: connection.connected
Everything works well, but when the changes comes to GUI, the main thread hangs if 'implementation' thread continues to do something. I can see changes while using
Connections { target: connection function onConnectedChanged(inProgress) { console.log("connected", connected); } }
But if the 5 step (property binging) is used, gui stucks. I think the reason is QML re-requesting, using getter with invokeMethond and some kind of an deadlock as a result.
So does other common practice exist to do so (if I'm doing it wrong)? Or maybe memory duplication can solve the issue (with not so sufficient memory usage (bools, ints and so on)
@St-Stanislav said in Sync objects properties in different threads to display in QML:
'interface' has Q_PROPERTY but without a field (to prevent memory usage duplication)
Clearly, this is the design choice which forced you into app getting stuck. If the data is not counted gigabytes, I would rather recommend you duplicate the data. This way you will gain a lot actually:
- no GUI blocking
- much simpler implementation (interface will just respond to signals from thread. QML will just respond to signals from the interface)
- no worry about mutextes etc.
- 'implementation' has a