I am running a programme that has multithreading . The programme firstly has a main / UI thread running in it. In this programme I have a worker and handler class.
The worker class is having a simulate function which simply generates the random number. The simulate function continuously generates the number without blocking any thread i.e. via Qtconcurrent.
From the main/UI thread I have put this worker class into new thread. The handler class is running in main /UI thread and is responsible to communicate with worker class running in other thread via signal slot.
So far everything is ok.
Problem starts when i try to close the programme by simply clicking on app cross button. The programme sort of hangs it does not close. However when i dont put worker in another class and run worker class from same main /UI thread then there is no problem and programme exits with 0.
So my question is how to stop Qtconcurrent is another thread and finally close the another thread aswell.
Thank You.
main.cpp
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QThread l_newThread;
Worker* l_worker = new Worker();
handler * l_handler = new handler();
l_worker->moveToThread(&l_newThread);
QObject::connect(&l_newThread, &QThread::started, l_worker, &Worker::Init);
QObject::connect(l_handler,&handler::toStop_Signal,&l_newThread, &QThread::quit);
QObject::connect(l_worker, &Worker::toStop_Signal_Worker, l_handler,&handler::toStop_Slot);
QObject::connect(&app,&QCoreApplication::aboutToQuit, l_worker, &Worker::stop);
// QObject::connect(&app,&QCoreApplication::aboutToQuit, &l_newThread, &QThread::quit);
l_newThread.start();
// l_worker->Init();
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
int result = app.exec();
l_newThread.wait();
return result;
}
worker.cpp
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker:: Init()
{
m_simulation = true;
simulate();
}
void Worker::simulate()
{
QtConcurrent::run([this]{
QRandomGenerator generator;
while (m_simulation) {
qint32 t = generator.bounded(0,100);
qDebug() << t;
qDebug() << "sleeping for 1 second";
QThread::sleep(1);
}
if (!m_simulation) {
qDebug() << "Killing the concurrent thread";
// QThread::currentThread()->exit();
emit toStop_Signal_Worker();
}
});
}
void Worker::stop()
{
m_simulation = false;
}
handler.cpp
#include "handler.h"
handler::handler(QObject *parent) : QObject(parent)
{
}
void handler::toStop_Slot()
{
emit toStop_Signal();
}
results
QML debugging is enabled. Only use this in a safe environment. 19 sleeping for 1 second 55 sleeping for 1 second 70 sleeping for 1 second 69 sleeping for 1 second Killing the concurrent thread
What probably happens here: the signal toStop_Signal
which is meant to quit l_newThread
is never delivered, because when it's emitted the event loop is already dead and gone. Hence, your program is stuck waiting for the thread in l_newThread.wait();
.
I don't fully get why you start this thread at all, just to use QtConcurrent::run
right after and span yet another thread ...
Anyway, once you're sure your worker has stopped (and you are, according to the output you posted), you can safely quit the (basically useless) thread directly in your main
:
int result = app.exec();
l_newThread.exit(); //just quit it
l_newThread.wait();
return result;
Then you can get rid of this connection:
QObject::connect(l_handler,&handler::toStop_Signal,&l_newThread, &QThread::quit);
and (I guess) of the handler altogether.