Why QThread still working, when work is done?
-
@JKSH Thank you for answer. I know that I have to use
isInterruptionRequested()
andrequestInterruption()
. But now I ask about something different.I would like ( now ) to have an application, which calculate what I want ( calculate() method in second thread ) even if I close the application. But when it finish calculates, application should close in correct way. And now ( my code ) I have situation that my application wait to finish calculates, but when they are finished, my application still is running ( I wait on
thread->wait
).Maybe when I quit event loop in second thread, this thread doesn't send
finished()
signal and I will wait inthread->wait()
forever?I ask about it, not to solved a problem, but to understand how quit() works, and why I have to still wait on
thread->wait
-
@JKSH The problem is
QCoreApplication::processEvents();
When I delete this line from my code - everything is ok. When this line is in my code - I wait in
thread->wait()
forever. Why? -
@JonB Using
processEvents()
doesn't make sense in my code. I tried something different and accidentally add this method. And now I would like to know, what's going on.Can you explain me what means
It's probably hanging in that when the main UI thread has gone away/is no longer running the UI loop.
?I know there is an event loop, which is in the main.cpp file:
return a.exec();
So when I close app and my code is in mainWindow's destructor I can't receive signals, because mainWindow is no longer in
a.exec()
?EDIT:
I don't see link between
processEvents()
andIt's probably hanging in that when the main UI thread has gone away/is no longer running the UI loop.
-
This works fine for me:
class Worker : public QObject { public: void calculate() { QThread::sleep(20); QCoreApplication::processEvents(); } }; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow() { thread = new QThread(this); worker = new Worker; worker->moveToThread(thread); thread->start(); QTimer::singleShot(0, worker, &Worker::calculate); } ~MainWindow() { thread->quit(); thread->wait(); } private: QThread *thread; Worker *worker; }; int main(int argc, char **argv) { QApplication app(argc, argv); MainWindow mw; mw.show(); return app.exec(); } #include "main.moc"
Please provide a minimal compilable example.
-
@Christian-Ehrlicher Your code is ok?
I think I can't add parent to
worker = new Worker(this);
I have error:
QObject::moveToThread: Cannot move objects with a parent
EDIT:
When I delete parent I get the same situation: I wait onthread->wait()
EDIT2:
My code:int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); thread = new QThread(this); worker = new Worker; worker->moveToThread(thread); thread->start(); QTimer::singleShot(0, worker, &Worker::calculate); } MainWindow::~MainWindow() { thread->quit(); qInfo()<<"BEFORE WAIT"; thread->wait(); qInfo()<<"AFTER WAIT"; delete ui; } void Worker::calculate() { QThread::sleep(20); qInfo()<<"AFTER SLEEP"; QCoreApplication::processEvents(); }
-
@Christian-Ehrlicher Your code is ok?
I think I can't add parent to
worker = new Worker(this);
I have error:
QObject::moveToThread: Cannot move objects with a parent
EDIT:
When I delete parent I get the same situation: I wait onthread->wait()
EDIT2:
My code:int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); thread = new QThread(this); worker = new Worker; worker->moveToThread(thread); thread->start(); QTimer::singleShot(0, worker, &Worker::calculate); } MainWindow::~MainWindow() { thread->quit(); qInfo()<<"BEFORE WAIT"; thread->wait(); qInfo()<<"AFTER WAIT"; delete ui; } void Worker::calculate() { QThread::sleep(20); qInfo()<<"AFTER SLEEP"; QCoreApplication::processEvents(); }
@qwe3 said in Why QThread still working, when work is done?:
@Christian-Ehrlicher Your code is ok?
You're right, it was a slightly outdated version. Adjusted my code but still works fine.
Your code is not compilable at all so I can't test yours. Please provide a minimal compilable example similar to mine without any ui file or other unneeded stuff. -
Code:
#include <QApplication> #include <QThread> #include <QTimer> #include <QMainWindow> #include <QDebug> class Worker : public QObject { public: void calculate() { qInfo()<<"START SECOND THREAD"; QThread::sleep(20); QCoreApplication::processEvents(); qInfo()<<"END SECOND THREAD"; } }; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow() { thread = new QThread(this); worker = new Worker; worker->moveToThread(thread); thread->start(); QTimer::singleShot(0, worker, &Worker::calculate); } ~MainWindow() { thread->quit(); qInfo()<<"before"; thread->wait(); qInfo()<<"after"; } private: QThread *thread; Worker *worker; }; int main(int argc, char **argv) { QApplication app(argc, argv); MainWindow mw; mw.show(); return app.exec(); } #include "main.moc"
I only add libraries and debuq. So I start app and after 5 second I close app using X button. Now I wait additional 15 seconds and see on debug
END SECOND THREAD
. And my app is still running. I have to close it in Qt Creator clicking red square. And have information:21:03:25: The program has unexpectedly finished.
I don't see on debug
after
-
Works fine for me with Qt5.15 on linux but have the same effect on windows. Maybe it's worth opening a Qt bug report.
-
@Christian-Ehrlicher Thank you for help, but I don't understand this:
but have the same effect on windows
Which option:
- On linux everything is ok, but on windows you have the same problem like me
- On linux and windows everything is ok
?
-
@Christian-Ehrlicher Thank you for help, but I don't understand this:
but have the same effect on windows
Which option:
- On linux everything is ok, but on windows you have the same problem like me
- On linux and windows everything is ok
?
@qwe3 Since @Christian-Ehrlicher suggested to open a bug report it works on Linux but not on Windows (in case 2 there would not be any need to file a bug report).