Как закрыть программу при запуске qtconcurrent из другого потока в qt

Я запускаю программу с многопоточностью. Сначала в программе работает основной поток/поток пользовательского интерфейса. В этой программе у меня есть рабочий класс и класс обработчика.

Рабочий класс имеет функцию имитации, которая просто генерирует случайное число. Функция имитации непрерывно генерирует число без блокировки какого-либо потока, т. е. через Qtconcurrent.

Из основного потока/потока пользовательского интерфейса я поместил этот рабочий класс в новый поток. Класс обработчика работает в основном потоке /UI и отвечает за связь с рабочим классом, работающим в другом потоке, через сигнальный слот.

Пока все в порядке.

Проблема начинается, когда я пытаюсь закрыть программу, просто нажав на крестик приложения. Программа как бы зависает, не закрывается. Однако, когда я не помещаю рабочего в другой класс и запускаю рабочий класс из того же основного потока/потока пользовательского интерфейса, тогда проблем нет, и программа завершается с 0.

Итак, мой вопрос заключается в том, как остановить Qtconcurrent и, наконец, закрыть другой поток.

Спасибо.

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;
}

рабочий.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;
}

обработчик.cpp

#include "handler.h"

handler::handler(QObject *parent) : QObject(parent)
{

}

void handler::toStop_Slot()
{
    emit toStop_Signal();
}

Результаты

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

person Mandeep    schedule 27.11.2019    source источник


Ответы (1)


Что, вероятно, происходит здесь: сигнал toStop_Signal, который предназначен для выхода из l_newThread, никогда не доставляется, потому что, когда он испускается, цикл событий уже мертв и ушел. Следовательно, ваша программа застряла в ожидании потока в l_newThread.wait();.

Я не совсем понимаю, зачем вы вообще начинаете эту ветку, просто чтобы использовать QtConcurrent::run сразу после и охватить еще одну ветку...

В любом случае, как только вы убедитесь, что ваш воркер остановился (а вы, согласно опубликованному вами выводу), вы можете безопасно выйти из (в основном бесполезного) потока прямо в вашем main:

int result = app.exec();

l_newThread.exit(); //just quit it
l_newThread.wait();

return result;

Затем вы можете избавиться от этой связи:

QObject::connect(l_handler,&handler::toStop_Signal,&l_newThread, &QThread::quit);

и (я думаю) обработчика в целом.

person p-a-o-l-o    schedule 28.11.2019
comment
Спасибо, я попробовал, на этот раз QtConcurrent не остановился, поскольку он продолжает работать. Как убедиться, что сначала qt concurrent остановлен, а затем другой поток остановлен/завершен. - person Mandeep; 28.11.2019