在析构函数中调用quit并不会杀死QThread?

时间:2018-03-15 09:12:10

标签: c++ multithreading qt qt5 qthread

我通过QtCreator运行此代码 问题是,当我关闭输出窗口时,线程不会死亡。要杀死线程,我必须转到终端并通过查找其ID来手动终止它或使用Application output窗口上的红色方块按钮来杀死它。

除非我们按Alt F4关闭窗口,否则此应用程序应该永远运行。

源文件[cpp]:

#include "mainwindow.h"

Controller::Controller(QMainWindow *parent) : QMainWindow(parent)
{
    worker_obj.moveToThread(&workerThread);
    worker_obj.timerReceivePackets.moveToThread(&workerThread);

    connect(this, &Controller::operate, &worker_obj, &Worker::doSomething);

    connect(&workerThread, SIGNAL(started()), &worker_obj, SLOT(initialize()));

    connect(&worker_obj, &Worker::resultReady, this, &Controller::handleResults);

    connect(&workerThread, SIGNAL(finished()), &workerThread, SLOT(deleteLater()));

    workerThread.start();
}

Controller::~Controller()
{
    workerThread.wait();
    workerThread.quit();
    workerThread.terminate();
}

标题[h]

#ifndef Worker_H
#define Worker_H

#include <QMainWindow>
#include <QObject>
#include <QImage>
#include <QDebug>
#include <QThread>
#include <QTimer>

class Worker : public QObject
{
    Q_OBJECT

private:
public:

    QTimer timerReceivePackets;

    Worker(QObject * parent = 0) {}
    ~Worker() {}

public slots:
    void initialize()
    {
        connect (&timerReceivePackets, SIGNAL (timeout()),
                 this, SLOT (doSomething()));

        timerReceivePackets.start();
    }

    void doSomething()
    {
        while(1)
        {
            QString result;
                /* ... here is the expensive or blocking operation ... */
            emit resultReady(result);
        }
    }

signals:
    void resultReady(const QString &result);
};

class Controller : public QMainWindow
{
    Q_OBJECT
    QThread workerThread;

public:
    Worker worker_obj;

    Controller( QMainWindow *parent = 0 );
    ~Controller();

public slots:
    void handleResults(const QString &) {}

signals:
    void operate(const QString &);

};

#endif // Worker_H

1 个答案:

答案 0 :(得分:0)

以下是使用QWidget::closeEvent要求工作人员完成任务的解决方案。 立即关闭窗口(当主窗口出现问题时应用程序退出)将被忽略以正常终止线程并且只有在worker完成后才退出应用程序。这使得可以在退出应用程序之前保存在线程中完成的昂贵操作的状态。工作完成后QObject::deleteLater为工作人员调用,QThread::quit为线程在线程完全关闭后触发deleteLater。

控制器:

class Controller : public QMainWindow
{
    Q_OBJECT
public:
    explicit Controller(QMainWindow *parent = nullptr)
        : QMainWindow(parent), m_worker(new Worker)
    {
        QThread *thread = new QThread;
        m_worker->moveToThread(thread);
        connect(thread, &QThread::started, m_worker, &Worker::operate);
        connect(m_worker, &Worker::resultReady, this, &Controller::handleResults);
        connect(m_worker, &Worker::finished, thread, &QThread::quit);
        connect(thread, &QThread::finished, thread, &QObject::deleteLater);
        connect(m_worker, &Worker::finished, m_worker, &QObject::deleteLater);
        connect(m_worker, &Worker::finished, qApp, &QApplication::quit);
        thread->start();
    }

    virtual ~Controller() {}

public slots:
    void handleResults(const QString &result){
        qDebug() << result;
    }

protected:
    void closeEvent(QCloseEvent *event) override
    {
        m_worker->finish();
        event->ignore();
    }

private:
    Worker *m_worker;
};

工人:

class Worker : public QObject
{
    Q_OBJECT

public:
    explicit Worker(QObject *parent = nullptr)
        : QObject(parent), m_continue(false) {}
    virtual ~Worker() {}

public slots:
    void operate(){
        m_continue = true;
        static QString result;
        while(m_continue)
        {
            result.append('a');
            QThread::sleep(2);
            emit resultReady(result);
        }
        emit finished();
    }

    void finish() {
        m_continue = false;
    }

signals:
    void finished();
    void resultReady(const QString &result);

private:
    bool m_continue;
};