Exit QThread when GUI Application exits

1.3k views Asked by At

I have the following worker class:

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

    void Exit();

signals:
    void Finished();

public slots:
    void OnExecuteProcess();
};

In MediaWorker.cpp

void MediaWorker::Exit()
{
    emit Finished();
}

void MediaWorker::OnExecuteProcess()
{
    qDebug() << "Worker Thread: " << QThread::currentThreadId();
}

In my MainWindow I do the following:

this->threadMediaWorker = new QThread();
this->mediaWorker = new MediaWorker();
this->timerMediaWorker = new QTimer();
this->timerMediaWorker->setInterval(1000);

this->timerMediaWorker->moveToThread(this->threadMediaWorker);
this->mediaWorker->moveToThread(this->threadMediaWorker);

connect(this->threadMediaWorker, SIGNAL(started()), this->timerMediaWorker, SLOT(start()));
connect(this->timerMediaWorker, &QTimer::timeout, this->mediaWorker, &MediaWorker::OnExecuteProcess);

connect(this->mediaWorker, &MediaWorker::Finished, this->threadMediaWorker, &QThread::quit);
connect(this->mediaWorker, &MediaWorker::Finished, this->mediaWorker, &MediaWorker::deleteLater);
connect(this->threadMediaWorker, &QThread::finished, this->mediaWorker, &QThread::deleteLater);

this->threadMediaWorker->start();   

The threading is working properly. When I close the application I terminate the thread in the destructor:

MainWindow::~MainWindow()
{
    delete ui;

    this->mediaWorker->Exit();
}

so Exit() emits the Finished signal which will hopefully delete the qthread and mediaworker class.

My question is if this is the proper way of terminating both the thread and media worker class?

1

There are 1 answers

2
Alexander V On BEST ANSWER

My question is what is the proper way of terminating both the worker thread and media worker class?

You can just ensure that the 'media' object gets deleted while the main window gets destructed by using either QScopedPointer or std::unique_ptr.

class MainWindow : public QMainWindow {
     /// ...
     QThread m_workerThread;
     QScopedPointer<MediaWorker> m_pMediaObject;
     /// ...
};

void MainWindows::init()
{
   // ... other initialization skipped ...
   // for dynamic allocation of the object and keeping the track of it
   m_mediaObject.reset(new MediaWorker());
   m_workerThread.moveToThread(m_mediaObject.data());
}

void MainWindow::stopWorker()
{
    if (m_workerThread.isRunning())
    {
        m_workerThread.quit(); // commands Qt thread to quit its loop
                               // wait till the thread actually quits
        m_workerThread.wait(); // possible to specify milliseconds but
                               // whether or not to limit the wait is
                               // another question
    }
}

If the worker thread used for updating the UI it makes sense to attempt to stop the worker thread before the UI objects released in

void MainWindow::closeEvent(QCloseEvent *)
{
   stopWorker();
}

But there is a chance that the main window never gets closeEvent() called before the destruction so we should handle that:

MainWindow::~MainWindow()
{
   stopWorker();

   // it also destroys m_mediaObject
}