Troubles with multithreading
-
Hello, and happy new year to all!
I'm having severe troubles implementing a multithreaded application utilizing C++ for a worker thread, and implementing my UI using QML. Although I reckon this is a classical problem and has been asked many times, I am unfortunately still having issues that impede the development of this application.What I'm trying to do is a simple "Hello World" application, a black screen with white text (set by QML), that is updated every second by a worker thread in such a way that said text is updated, along with the color of the background. To do so, I tried defining a 'hasWork' signal in my .h file. I tried to receive said signal in my .qml file and had no success.
I need to have this worker thread accessible in some way from my QML code, and as such, I tried to register the object that exists in this thread as a singleton from my main.cpp file. This works if my singleton exists in the same thread as the GUI thread, but if it's not, I see on the QML Debugger a message saying "Non-existent attached object". Can someone please help me in solving this?
My code is available here: https://github.com/luisfilipels/testThreadQt
The relevant files are main.cpp, main.qml, windowupdater.cpp and windowupdater.h. If something isn't clear, please tell and I will try to explain it better. Thank you.
-
Hi and welcome to the forums
I think the issue is that QQmlApplicationEngine and your QObject need to be in same thread which they are not when you use moveToThreadThis poster however sounds like he found a workaround using
a WorkerInterface design. -
@mrjj
Thank you for your response. I tried my best to replicate the approach from the poster of the link you shared, but the "Non-existent attached object" persists, and what's worse, I now get "QQmlApplicationEngine failed to load component". Any leads to what may be wrong? I updated my repo with the new code. -
Hi.
And you reused his class WorkerInterface : public QObject
that hold the thread and so on ?Did you try the whole sample ?
-
@luisfilipels
Hi
A day is not late :)
Hmm. Did you try his sample to test it actually does work still?
(from 2015)Update:
I tested the code and it gives no errors and seems to work fine.
Here is the test project
https://www.dropbox.com/s/itp2wycpiwk6l70/threadQML.zip?dl=0 -
@mrjj
I just tried running the test project you sent, and it does seem to be working correctly my PC.
I'm going to compare my code and his code to see what may be wrong. I'll update my post with what I find. Thank you for your help thus far.edit:
I finally got it working! But with a problem: I had to redefine my interface as no longer being a singleton. I had to instantiate it from the QML code. Is there something wrong with how I created my singleton? :( -
@luisfilipels
Hi
Well as long as the singleton is created after QApplication ,
it should not matter much even if used in a singleton pattern.
Is the code from first link the actual code ? -
@mrjj said in Troubles with multithreading:
@luisfilipels
Hi
Well as long as the singleton is created after QApplication ,
it should not matter much even if used in a singleton pattern.My main.cpp, as it was originally (using the singleton pattern):
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QThread> #include <QObject> #include <QQmlContext> #include "windowupdater.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; qDebug() << "Starting application" << endl; UpdaterInterface::getInstance(); qmlRegisterSingletonType<UpdaterInterface>("threadtest", 1, 0, "Updater", &UpdaterInterface::UpdaterInterfaceProvider); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
Is the code from first link the actual code ?
Yes, it's the code as it was when I was using the singleton pattern. Here is the code as it is now, functional as it is: https://github.com/luisfilipels/testThreadQt/tree/noSingleton
-
@luisfilipels
Hi
I think its the use of static that makes it unhappy as when you flag a member function with it
it becomes a class function and there is no "this" as such.
But im not sure if that was the actual problem.Did it show some error when a singleton ?
-
@mrjj said in Troubles with multithreading:
@luisfilipels
Hi
I think its the use of static that makes it unhappy as when you flag a member function with it
it becomes a class function and there is no "this" as such.Do you mean the static constructor? But wouldn't it have to be static in order to be used as a singleton?
Did it show some error when a singleton ?
Yes, the ones I spoke about before. "Non-existent attached object" on the Updater.onUpdateGUI on main.qml, and "QQmlApplicationEngine failed to load component".
-
Just replying to say I got it working 100% as I expected, while still registering my object as a singleton!
I just added a Connections element to my QML code, with the singleton object as its target. Thank you for your help, @mrjj