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

Help using Qthread and signal/slot



  • Hello,

    I'm a beginner and i try using qt with multi-thread and signal/slot.
    This is my worker class worker.h:

    #ifndef GSTIMPL_H
    #define GSTIMPL_H
    
    #include <QObject>
    #include <QThread>
    #include <QDebug>
    
    class Worker : public QObject {
        Q_OBJECT
    public:
        Worker();
        ~Worker();
    public slots:
        void Process();
        void Stop();
    signals:
        void finished();
    private:
        bool m_play;
    };
    
    #endif // GSTIMPL_H
    

    the corresponding worker.cpp:

    #include "Worker.h"
    
    Worker::Worker() { // Constructor
        qDebug() << "-------------- Worker Constructor --------------" << endl;
        m_play = true;
    }
    
    Worker::~Worker() { // Destructor
        qDebug() << "-------------- Worker Destructor --------------" << endl;
    }
    
    void Worker::Process() { // Process. Start processing data.
    
        qDebug() << "-------------- Worker Process --------------" << endl;
    
    
        while(m_play == true)
        {
            qDebug("Hello World!");
            QThread::sleep(1);
        }
    
        emit finished();
    }
    
    void Worker::Stop()
    {
        qDebug() << "-------------- Worker Stop --------------" << endl;
        m_play = false;
    }
    
    

    My controller class:

    #ifndef CONTROLLER_H
    #define CONTROLLER_H
    
    #include <QObject>
    #include <QThread>
    #include "Worker.h"
    
    class Controller : public QObject
    {
        Q_OBJECT
        QThread workerThread;
    
    public:
        Controller();
    
    public slots:
    
    signals:
        void Play();
        void Stop();
    
    };
    
    #endif // CONTROLLER_H
    
    

    and the corresponding controller.cpp:

    #include "controller.h"
    
    
    Controller::Controller()
    {
        qDebug() << "-------------- Controller Constructor --------------" << endl;
    
        Worker* worker = new Worker();
        worker->moveToThread(&workerThread);
    
        connect(&workerThread, SIGNAL (started()), worker, SLOT (Process()));
        connect(worker, SIGNAL (finished()), &workerThread, SLOT (quit()));
        connect(worker, SIGNAL (finished()), worker, SLOT (deleteLater()));
        connect(&workerThread, SIGNAL (finished()), &workerThread, SLOT (deleteLater()));
    
        connect(this, SIGNAL (Stop()), worker, SLOT (Stop()));
    
        workerThread.start();
    
        emit Stop();
    }
    

    And this is my main:

    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        Controller c;
    
        return app.exec();
    }
    
    

    This is the output i get :

    *Starting /opt/GstBind/bin/GstBind...

    QML debugging is enabled. Only use this in a safe environment.
    Using Wayland-EGL
    -------------- Controller Constructor --------------

    -------------- Worker Constructor --------------

    -------------- Worker Process --------------

    Hello World!

    Hello World!
    Hello World!
    Hello World!
    Hello World!
    User requested stop. Shutting down...
    Process killed by signal*

    As you can see my problem is about signal/slot Stop(). It is never called whereas in my controller constructor it should be ! and so never printed too.



  • @fd101283 said in Help using Qthread and signal/slot:

    QThread workerThread;

    Hi! There's a double free in your code: workerThread is a member variable of Controller (thus gets automatically destroyed by the C++ runtime when Controller gets destroyed) and at the same time you connected workerThread's finished signal to its deleteLater slot.



  • @Wieland said in Help using Qthread and signal/slot:

    Hi! There's a double free in your code: workerThread is a member variable of Controller (thus gets automatically destroyed by the C++ runtime when Controller gets destroyed) and at the same time you connected workerThread's finished signal to its deleteLater slot.

    Hi,
    In fact the code is extrated from here :
    https://wiki.qt.io/QThreads_general_usage

    BUt even without the free, i can't see Stop signal working!



  • I think it may be because you are emitting the signal from within the constructor which means that the event loop isn't running yet. Try replacing:

    emit Stop();
    

    with

    QTimer::singleShot(1000, [](){ emit Stop(); });
    

    This will ensure that the loop is running before the signal is emitted.


Log in to reply