Выход из QThread при выходе из приложения с графическим интерфейсом

У меня есть следующий рабочий класс:

class MediaWorker : public QObject
{
    Q_OBJECT
public:
    explicit MediaWorker(QObject *parent = 0);
    ~MediaWorker();

    void Exit();

signals:
    void Finished();

public slots:
    void OnExecuteProcess();
};

В MediaWorker.cpp

void MediaWorker::Exit()
{
    emit Finished();
}

void MediaWorker::OnExecuteProcess()
{
    qDebug() << "Worker Thread: " << QThread::currentThreadId();
}

В моем MainWindow я делаю следующее:

this->threadMediaWorker = new QThread();
this->mediaWorker = new MediaWorker();
this->timerMediaWorker = new QTimer();
this->timerMediaWorker->setInterval(1000);

this->timerMediaWorker->moveToThread(this->threadMediaWorker);
this->mediaWorker->moveToThread(this->threadMediaWorker);

connect(this->threadMediaWorker, SIGNAL(started()), this->timerMediaWorker, SLOT(start()));
connect(this->timerMediaWorker, &QTimer::timeout, this->mediaWorker, &MediaWorker::OnExecuteProcess);

connect(this->mediaWorker, &MediaWorker::Finished, this->threadMediaWorker, &QThread::quit);
connect(this->mediaWorker, &MediaWorker::Finished, this->mediaWorker, &MediaWorker::deleteLater);
connect(this->threadMediaWorker, &QThread::finished, this->mediaWorker, &QThread::deleteLater);

this->threadMediaWorker->start();   

Поток работает исправно. Когда я закрываю приложение, я завершаю поток в деструкторе:

MainWindow::~MainWindow()
{
    delete ui;

    this->mediaWorker->Exit();
}

поэтому Exit() выдает сигнал Finished, который, как мы надеемся, удалит класс qthread и mediaworker.

Мой вопрос заключается в том, является ли это правильным способом прекращения работы как потока, так и класса медиа-работника?


person adviner    schedule 31.12.2016    source источник


Ответы (1)


Мой вопрос заключается в том, как правильно завершить рабочий поток и рабочий класс медиа?

Вы можете просто убедиться, что объект «медиа» будет удален, а главное окно будет разрушено, используя либо QScopedPointer, либо std::unique_ptr.

class MainWindow : public QMainWindow {
     /// ...
     QThread m_workerThread;
     QScopedPointer<MediaWorker> m_pMediaObject;
     /// ...
};

void MainWindows::init()
{
   // ... other initialization skipped ...
   // for dynamic allocation of the object and keeping the track of it
   m_mediaObject.reset(new MediaWorker());
   m_workerThread.moveToThread(m_mediaObject.data());
}

void MainWindow::stopWorker()
{
    if (m_workerThread.isRunning())
    {
        m_workerThread.quit(); // commands Qt thread to quit its loop
                               // wait till the thread actually quits
        m_workerThread.wait(); // possible to specify milliseconds but
                               // whether or not to limit the wait is
                               // another question
    }
}

Если рабочий поток используется для обновления пользовательского интерфейса, имеет смысл попытаться остановить рабочий поток до того, как объекты пользовательского интерфейса будут выпущены в

void MainWindow::closeEvent(QCloseEvent *)
{
   stopWorker();
}

Но есть шанс, что главное окно никогда не вызовет closeEvent() перед уничтожением, поэтому мы должны справиться с этим:

MainWindow::~MainWindow()
{
   stopWorker();

   // it also destroys m_mediaObject
}
person Alexander V    schedule 01.01.2017
comment
Спасибо за образец - person adviner; 16.01.2017
comment
Документация Qt для QThread также содержит четкий пример использования, включая предпочтительный процедура запуска и выхода. - person m7913d; 22.04.2017