Exit QThread Cleanly



  • I am currently developing a GUI front-end application for DVR. After completing the coding part of it, I have tested it many times and it is working fine.

    I am using QThread in my code for checking the state of the backend server 24X7. I do not have any proper solution for closing second thread cleanly when my main thread i.e. GUI thread quits.

    Here is the code which I have been using right now for second thread.

    @void thread::run()
    {

    forever
    {
    forever
    {
    checking some condition........
    emit <signal>;
    break;
    }
    forever
    {
    checking some condition........
    emit <signal>;
    break;
    }
    }
    }@

    Please suggest any solution for the above scenario.



  • Before I answer your question I will first say that, despite examples given in the docs, it is generally considered a bad idea to subclass QThread and instead create a worker object that is moved into a thread. To stop a QThread you need to call quit() and, if that fails, terminate(). The issue here is that you're running a blocking method and no event loop so these methods will not work on there own. What you therefore need is a flag that is checked on every iteration of the forever loop and set by a signal/slot call from your main thread when the GUI exits. The following files form a minimal working example:

    widget.h
    @
    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QWidget>

    class QThread;

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    private:
    QThread *thread;

    signals:
    void stopThread();

    public slots:
    void start();
    void tick();
    };

    #endif // WIDGET_H
    @

    widget.cpp
    @
    #include "widget.h"
    #include "threaded.h"

    #include <QVBoxLayout>
    #include <QPushButton>
    #include <QThread>
    #include <QDebug>

    Widget::Widget(QWidget *parent) :
    QWidget(parent)
    {
    QVBoxLayout *l=new QVBoxLayout(this);

    QPushButton *startButton=new QPushButton("Start", this);
    connect(startButton, SIGNAL(clicked()), this, SLOT(start()));
    l->addWidget(startButton);
    

    }

    Widget::~Widget()
    {
    if(thread->isRunning()){
    emit stopThread();
    thread->quit();
    if(!thread->wait(5000)){
    thread->terminate();
    if(!thread->wait(5000)) qDebug() << "Failed to terminate!";
    }
    }
    }

    void Widget::start(){
    thread=new QThread();
    Threaded *threaded=new Threaded();
    connect(this, SIGNAL(stopThread()), threaded, SLOT(stop()));
    connect(threaded, SIGNAL(tick()), this, SLOT(tick()));
    connect(thread, SIGNAL(started()), threaded, SLOT(work()));
    threaded->moveToThread(thread);
    thread->start();
    }

    void Widget::tick(){
    qDebug() << "tick";
    }
    @

    threaded.h
    @
    #ifndef THREADED_H
    #define THREADED_H

    #include <QObject>

    class Threaded : public QObject
    {
    Q_OBJECT
    public:
    explicit Threaded(QObject *parent = 0);

    private:
    bool mStop;

    signals:
    void tick();

    public slots:
    void work();
    void stop();
    };

    #endif // THREADED_H
    @

    threaded.cpp
    @
    #include "threaded.h"

    #include <QMutex>
    #include <QWaitCondition>
    #include <QCoreApplication>

    Threaded::Threaded(QObject *parent) :
    QObject(parent), mStop(false)
    {}

    void Threaded::work(){
    QMutex dummy;
    QWaitCondition waitCondition;

    forever{
        dummy.lock();
        waitCondition.wait(&dummy, 1000);
        emit tick();
        dummy.unlock();
        QCoreApplication::processEvents();
        if(mStop) break;
    }
    

    }

    void Threaded::stop(){
    mStop=true;
    }
    @

    main.cpp
    @
    #include <QtGui/QApplication>
    #include "widget.h"

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec&#40;&#41;;
    

    }
    @

    Hope this helps ;o)


Log in to reply
 

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