在析构函数中调用 quit 不会杀死 QThread?
Calling quit in destructor doesn't kill the QThread?
我运行这段代码通过QtCreator。
问题是,当我关闭输出 window 时,线程不会死掉。要终止线程,我必须去终端并通过查找它的 ID 手动终止它,或者使用 Application output
window 上的红色方形按钮来终止它。
除非我们按 Alt F4 关闭 window,否则此应用程序应该永远 运行ning。
源文件[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();
}
Header[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
下面是使用 QWidget::closeEvent 要求工作人员完成其任务的解决方案。 立即 window 关闭(当 main window 有问题时应用程序退出)被忽略以优雅地终止线程 并且应用程序是只有在工人完成后才退出。这使得在退出应用程序之前保存在线程中完成的昂贵操作的状态成为可能。 worker完成后QObject::deleteLater
为worker调用,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;
};
我运行这段代码通过QtCreator。
问题是,当我关闭输出 window 时,线程不会死掉。要终止线程,我必须去终端并通过查找它的 ID 手动终止它,或者使用 Application output
window 上的红色方形按钮来终止它。
除非我们按 Alt F4 关闭 window,否则此应用程序应该永远 运行ning。
源文件[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();
}
Header[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
下面是使用 QWidget::closeEvent 要求工作人员完成其任务的解决方案。 立即 window 关闭(当 main window 有问题时应用程序退出)被忽略以优雅地终止线程 并且应用程序是只有在工人完成后才退出。这使得在退出应用程序之前保存在线程中完成的昂贵操作的状态成为可能。 worker完成后QObject::deleteLater
为worker调用,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;
};