Solved terminating a thread
-
@SGaist OK, I understand the mechanics of the worker thread, but how to invoke the wait is a bit of a mystery. Here's my main:
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget widget; Worker worker; QObject::connect(&worker, &Worker::newResponseText, &widget, &Widget::addText); QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit); widget.show(); worker.start(); return a.exec(); }
I don't see:
- where to put the wait(), given that a.exec() runs infinitely.
- how to terminate the application (worker::run() could send a signal after it exits its loop, I suppose).
-
You could use a lambda that calls
doQuit
and thenwait
rather than than connecting doQuit directly. Or you can integratewait
indoQuit
.Add a signal to your Worker class that you emit at the end of the loop.
-
@mzimmers said in terminating a thread:
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget widget; Worker worker; QObject::connect(&worker, &Worker::newResponseText, &widget, &Widget::addText);
// Invoke directly as there's no running event loop to process the slot QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit, Qt::DirectConnection); // Connect the aboutToQuit from the `QCoreApplication` so you don't hang when the button's not pressed QObject::connect(&a, &QCoreApplication::aboutToQuit, &worker, &Worker::doQuit, Qt::DirectConnection);
widget.show(); worker.start();
// Store the return value and then wait for the thread to exit int retValue = QApplication::exec(); worker.wait(); // After the thread has finished, return from main() return retValue; }
This is all assuming
doQuit
is what @SGaist wrote - raising an atomic flag to tell the thread to quit.Btw, you can use
QThread::requestInterruption
andQThread::isInterruptionRequested
instead of rolling your own. -
@SGaist so my worker thread will signal the QApplication, so that the QApplication can quit. Correct?
I'm still lost regarding the use of wait(). It can't reside in the worker object, as a thread can't wait for itself. And I have no context from which to use it in main(). Do I need a parent class/object for my worker?
-
See @kshegunov's excellent alternative.
-
@kshegunov so, do I correctly understand that, in your example, the QApplication will terminate before the worker thread?
I didn't know you could do that...
-
You can exit the (main) event loop at any time you want, you need to wait before returning from
main()
so your process doesn't terminate before the thread has done so. So yes, you can exit the loop before returning frommain()
. :)PS.
QCoreApplication::exec
does practically nothing, it's a convenience function, you can substitute it with:QEventLoop loop; return loop.exec();
-
@kshegunov well, isn't that something. Very nice.
I implemented it a bit differently from your example:
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget widget; Worker worker; int rc; QObject::connect(&worker, &Worker::newResponse, &widget, &Widget::addText); QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit); QObject::connect(&worker, &Worker::reachedEndOfThread, &a, &QApplication::exit); widget.show(); worker.start(); rc = a.exec(); worker.wait(); return rc; } Seems to work fine. Thanks, guys.
-
You should still connect the
aboutToQuit
signal, as you may click thex
in the top right of the window, which wouldn't trigger yourdoQuit
. -
Done. Thanks again.