Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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.


  • Lifetime Qt Champion

    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 moveToThread

    This poster however sounds like he found a workaround using
    a WorkerInterface design.

    https://forum.qt.io/topic/62073/qthread-qml



  • @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.


  • Lifetime Qt Champion

    @luisfilipels

    Hi.
    And you reused his class WorkerInterface : public QObject
    that hold the thread and so on ?

    Did you try the whole sample ?



  • @mrjj
    I apologize for the late response.
    I do believe I have adapted most of the relevant code from the source you posted into my code, including the interface (it's in windowupdater.h), yet I still get the same errors as before.


  • Lifetime Qt Champion

    @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? :(


  • Lifetime Qt Champion

    @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


  • Lifetime Qt Champion

    @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