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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.