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

Controller-Worker thread qml signal repeating



  • Hello,
    My application communicates to an USB device by custom protocol. I'm moving blocking methods to another thread. And it looks something like this:

    cpp side:
    
    #include <QObject>
    #include <QThread>
    #include <QDebug>
    
    class Worker : public QObject
    {
        Q_OBJECT
    public:
        explicit Worker(QObject *parent = nullptr) : QObject(parent) {}
    
    signals:
        void blockingFunction1Finished();
    
    public slots:
        void blockingFunction1() {
            qDebug() << "blocking function1 started";
            QThread::sleep(1);
            emit blockingFunction1Finished();
        }
    };
    
    class Controller : public QObject
    {
        Q_OBJECT
    public:
        explicit Controller(QObject *parent = nullptr) : QObject(parent) {
            Worker *worker = new Worker;
            worker->moveToThread(&mWorkerThread);
            connect(this, &Controller::beginBlockingFunction1, worker, &Worker::blockingFunction1);
            connect(worker, &Worker::blockingFunction1Finished, this, &Controller::blockingFunction1Finished);
            mWorkerThread.start();
        }
    
        Q_INVOKABLE void startBlockingFunction1() {
            emit beginBlockingFunction1();
        }
    
    signals:
        void beginBlockingFunction1();
        void blockingFunction1Finished();
    
    public slots:
    
    private:
        QThread mWorkerThread;
    };
    
    register:
    qmlRegisterType<Controller>("Qt.Test", 1, 0, "Controller");
    
    qml side:
    
    import Qt.Test 1.0
    
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Controller {
            id: controller
            onBlockingFunction1Finished: console.log("blocking function1 finished")
        }
    
        Button {
            onClicked: controller.startBlockingFunction1()
        }
    }
    

    What bugs me is that I have to? make 2 connections to know that blocking method finished. One connection on cpp side from Worker to Controller and one in qml side.

    Is there a way to get around connecting Worker signal to Controller connect(worker, &Worker::blockingFunction1Finished, this, &Controller::blockingFunction1Finished); and just have one connection in qml onBlockingFunction1Finished: console.log("blocking function1 finished").

    And lastly I believe that there is no elegant way to call Worker slot from qml without making a connection and writing a wrapper method to emit a signal:

        Q_INVOKABLE void startBlockingFunction1() {
            emit beginBlockingFunction1();
        }
    

    is this correct?


  • Moderators

    @Eligijus

    hi, there are a couple of things you can do, that I know of, to make your life a bit easier.

    first of, no need to wrap your signal in function to call it from qml. The Q_INVOKABLE macro also works directly for signals. Signals are (basically) just functions.

    AFAIK you can no simply access a signal in qml, that is emitted from a different Thread in a c++ backend.

    But you should be able to chain-connect one signal to another, that reduces the issue to one line of code



  • @J.Hilk Thanks for your feedback.
    Could you give me an example how would chain-connecting one signal to another would look like. Or what should I add to my example code to fix the issue?


  • Moderators

    @Eligijus said in Controller-Worker thread qml signal repeating:

    @J.Hilk Thanks for your feedback.
    Could you give me an example how would chain-connecting one signal to another would look like. Or what should I add to my example code to fix the issue?

    looking through your example, I think you're already doing that. this

    connect(worker, &Worker::blockingFunction1Finished, this, &Controller::blockingFunction1Finished);
    

    connects the signal from your worker to the signal of your controller.



  • This post is deleted!

Log in to reply