I want to know the correct way to create a QThread object, terminate it and wait for the termination in the main thread.
The problem I'm getting is that the wait() method of QThread doesn't return true (as i think it has) and blocks allways until the timeout has expired.
I temporally fixed this by calling quit() method before returning from the run() method in the worker thread, but I think it shoudn't be the correct way to do that.
In the QT Documentation says that wait() should return true if the thread has finished
(ie when it returns from run())
I'm using QT 5.9 and Linux.
Do anyone had this problem?
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
# include <QMainWindow>
# include "Worker.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_btnStart_clicked();
void on_btnStop_clicked();
private:
Worker *ProcWorker;
QThread ProcessThread;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
MainWindow.cpp:
# include "MainWindow.h"
# include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
this->ProcWorker = new Worker ();
this->ProcWorker->moveToThread(&this->ProcessThread);
QObject::connect (&this->ProcessThread, SIGNAL(started()), this->ProcWorker, SLOT(RunProcess()));
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::on_btnStart_clicked() {
this->ProcessThread.start ();
}
void MainWindow::on_btnStop_clicked() {
this->ProcWorker->Terminate ();
// It blocks until timeout has expired and return false.
bool ret = this->ProcWorker->thread()->wait (1000000);
}
Worker.h:
#ifndef WORKER_H
#define WORKER_H
# include <QObject>
# include <QThread>
class Worker : public QObject {
Q_OBJECT
private:
bool TerminateProcess;
public:
Worker() {
this->TerminateProcess = false;
}
void Terminate () {
this->TerminateProcess = true;
}
public slots:
void RunProcess () {
while (true) {
QThread::msleep(100);
if (this->TerminateProcess) {
break;
}
// Do something
}
// I need to add this to get wait() works
//this->thread()->quit ();
}
};
#endif
The thread does not stop running simply because your RunProcess
ends. Sending a quit
is a correct means of shutting down the thread.
That said, you have two other problems related to the threading:
TerminateProcess
flag is not guaranteed to be seen inside RunProcess
. You should use a QAtomicInt
or a QSemaphore
to ensure the worker thread sees the flag change. RunProcess
method blocks the event loop from running and shutting down the thread if you were to call quit
from the outside (or in Terminate
). You should either "do something" in the callback from a QTimer
or use the thread interruption mechanic ( QThread::requestInterruption
from the caller and QThread::interruptionRequested
inside the loop). A lot depends on your "Do something" code. If that spends minutes calculating digits of Pi without supporting a means of interruption, no amount of cooperation with the Qt event loop outside of it will save you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.