c++qtqthreadqtconcurrent

How to close the programme when running a qtconcurrent from another thread in qt


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

Solution

  • 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.