Как правильно выйти из приложения Qt с рабочим потоком? - PullRequest
0 голосов
/ 08 февраля 2019

Как лучше всего выходить из приложения Qt?Я делаю что-то вроде этого

int main(int argc, char *argv[])
{
    MyApplication app(argc, argv);
    return myApp.exec();
}

MyApplication::MyApplication( int& argc, char** argv ) : 
    QApplication( argc, argv )
{
    m_window= new MyWidget();
    m_worker= new MyWorker();
    m_threadWorker = new QThread;
    m_worker->moveToThread(m_threadWorker);

    connect(this, SIGNAL(aboutToQuit()),m_worker,SLOT(quit()));

    connect(m_worker, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
    connect(m_worker, SIGNAL(finished()), m_threadWorker, SLOT(quit()));
    connect(m_threadWorker, SIGNAL(finished()), m_threadWorker, SLOT(deleteLater()));

    m_threadWorker->start();
    m_window->show();
}

MyApplication::~MyApplication()
{
    m_window->deleteLater();
    qDebug()<<"MyApplication::~MyApplication()";
}

MyWorker::quit()
{
    //longer ending operations freeing resources
    emit finished();
    qDebug() << "MyWorker::quit() emit finished()";
}

MyWorker::~MyWorker()
{
    qDebug() << "MyWorker::~MyWorker()";
}

, проблема в том, что часто рабочий деструктор не запускается.Я обеспокоен тем, что неправильное завершение работника может время от времени вызывать сбой приложения.Я использую камеру в этом потоке, поэтому, если петля камеры активна, освобождение занимает больше времени, и обычно готовое изображение никогда не отправляется, и поэтому деструктор никогда не вызывается.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Спасибо за комментарии, это решение работает

int main(int argc, char *argv[])
{
    MyApplication app(argc, argv);
    return myApp.exec();
}

MyApplication::MyApplication( int& argc, char** argv ) : 
QApplication( argc, argv )
{
    m_window= new MyWidget();
    m_worker= new MyWorker();
    m_threadWorker = new QThread;
    m_worker->moveToThread(m_threadWorker);

    connect(this, SIGNAL(aboutToQuit()),m_worker,SLOT(quit()),Qt::QueuedConnection);

    connect(m_worker, SIGNAL(finished()), m_threadWorker, SLOT(quit()),Qt::DirectConnection);
    connect(m_threadWorker, SIGNAL(finished()), m_worker, SLOT(deleteLater()));

    m_threadWorker->start();
    m_window->show();
}

MyApplication::~MyApplication()
{
    m_threadWorker->wait();
    m_threadWorker->deleteLater();
    m_window->deleteLater();
    qDebug()<<"MyApplication::~MyApplication()";
}

MyWorker::quit()
{
    //longer ending operations freeing resources
    emit finished();
    qDebug() << "MyWorker::quit() emit finished()";
}

MyWorker::~MyWorker()
{
   qDebug() << "MyWorker::~MyWorker()";
}
0 голосов
/ 08 февраля 2019

Проблема в том, что aboutToQuit не ждет, когда рабочий закончит работу.Вы должны явно подождать, пока он сделает это:

connect(this, &MyApplication::aboutToQuit,
        this, &MyApplication::stopWorker);

// also, change up your connects a little to make shure everything gets deleted properly
connect(m_worker, &MyWorker::finished, 
        m_threadWorker, &QThread::quit,
        Qt::DirectConnection); //direct connection is needed, because you are blocking the main thread by waiting
connect(m_threadWorker, &QThread::finished,
        m_worker, &MyWorker::deleteLater);


MyApplication::stopWorker() {
    QMetaObject::invokeMethod(m_worker, "quit");
    m_threadWorker->wait();
    m_threadWorker->deleteLater();
}

Это, однако, "заморозит" ваше приложение, ожидая, пока работник завершит работу.Если вы хотите оставаться отзывчивым во время ожидания, вместо этого используйте локальный QEventLoop внутри MyApplication::stopWorker и используйте его как:

MyApplication::stopWorker() {
    QEventLoop stopLoop;
    connect(m_threadWorker, &QThread::finished,
            &stopLoop, &QEventLoop::quit);
    QMetaObject::invokeMethod(m_worker, "quit");
    stopLoop.exec();
    m_threadWorker->deleteLater();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...