从 Qt4.4 版本之后,因为 QThread 的 run 方法创建新线程这样实现与 Qt 设计的理念不符,Qt 主推使用 moveToThread 方法来创建新线程。QThread 应该被看做是操作系统线程的接口或控制点,而不应该包含需要在新线程中运行的代码。需要运行的代码应该放到一个 QObject 的子类中,然后将该子类的对象 moveToThread 到新线程中。主要操作步骤如下:
具体代码如下:
1:要放入新线程的 Worker 类
h 文件:
#ifndef WORKER_H
#define WORKER_H
#include
/*****************************************************************************************
@copyright 2013-2020
@author qiaowei
@contact [email protected]
@version 1.0
@date 2021-01-09
@brief 工人类,主要方法do_something打印工人对象所在线程的id
******************************************************************************************/
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
signals:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-24
@brief 调用Controller::print_thread方法
***************************************************************************/
void result_ready(const QString& content);
public slots:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 打印Worker对象所在线程id
***************************************************************************/
void do_something();
};
#endif // WORKER_H
cpp 文件:
#include
#include
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::do_something()
{
emit result_ready("Hello");
// int i(0);
// while (i < 20) {
// qDebug() << "I'm working in Worker's thread:" << (quint64) QThread::currentThreadId();
// ++i;
// }
qDebug() << "I'm working in Worker's thread:" << (quint64) QThread::currentThreadId();
}
2:操纵 Worker 类对象的 Controller 类
h 文件:
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include
QT_BEGIN_NAMESPACE
class Worker;
QT_END_NAMESPACE
/*****************************************************************************************
@copyright 2013-2020
@author qiaowei
@contact [email protected]
@version 1.0
@date 2021-01-06
@brief 控制线程创建、启动
******************************************************************************************/
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
~Controller();
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-06
@brief 将对象worker_移入子线程work_thread_,启动子线程
***************************************************************************/
void move_work_to_thread();
signals:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 调用worker_::do_something方法
***************************************************************************/
void start_running();
public slots:
void print_thread() const;
private:
void setup_connections();
void print_thread_id() const;
private:
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 子线程
***************************************************************************/
QThread* work_thread_;
/***************************************************************************
@author qiaowei
@version 1.0
@date 2021-01-07
@brief 放入子线程work_thread_的对象worker_
***************************************************************************/
Worker* worker_;
};
#endif // CONTROLLER_H
cpp 文件:
#include
#include
#include "controller.h"
#include "worker.h"
Controller::Controller(QObject *parent) :
QObject(parent),
work_thread_(new QThread()),
worker_(new Worker())
{
setup_connections();
print_thread_id();
move_work_to_thread();
}
Controller::~Controller()
{
work_thread_->quit();
work_thread_->wait();
delete work_thread_;
if (nullptr == work_thread_) {
qDebug()<< "nullptr";
} else {
work_thread_ = nullptr;
}
}
void Controller::move_work_to_thread()
{
worker_->moveToThread(work_thread_);
// 启动子线程。不启动子线程,worker_对象的方法不会被调用(因为运行的环境没启动)
work_thread_->start();
}
void Controller::print_thread() const
{
// int i(0);
//
// while (i < 20) {
// print_thread_id();
// ++i;
// }
print_thread_id();
}
void Controller::setup_connections()
{
connect(this,
&Controller::start_running,
worker_,
&Worker::do_something);
connect(worker_,
&Worker::result_ready,
this,
&Controller::print_thread);
}
void Controller::print_thread_id() const
{
qDebug()<< "Controller::Controller = " << (quint64) QThread::currentThreadId();
}
触发线程的 ui 类
h 文件:
#ifndef CONTROLLER_DIALOG_H
#define CONTROLLER_DIALOG_H
#include
QT_BEGIN_NAMESPACE
class Controller;
QT_END_NAMESPACE
namespace Ui {
class Controller_dialog;
}
/*****************************************************************************************
@copyright 2013-2020
@author qiaowei
@contact [email protected]
@version 1.0
@date 2021-01-09
@brief 操作多线程的ui
******************************************************************************************/
class Controller_dialog : public QDialog
{
Q_OBJECT
public:
explicit Controller_dialog(QWidget *parent = nullptr);
~Controller_dialog();
private:
void setup_connections();
private:
Ui::Controller_dialog *ui;
Controller* controller_;
};
#endif // CONTROLLER_DIALOG_H
cpp 文件:
#include "controller_dialog.h"
#include "ui_controller_dialog.h"
#include "controller.h"
Controller_dialog::Controller_dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Controller_dialog),
controller_(new Controller())
{
ui->setupUi(this);
setup_connections();
setFixedSize(sizeHint());
}
Controller_dialog::~Controller_dialog()
{
delete ui;
delete controller_;
}
void Controller_dialog::setup_connections()
{
// 启动新线程
connect(ui->start_button_,
&QPushButton::clicked,
controller_,
&Controller::start_running);
// 关闭所有窗体,退出程序
connect(ui->quit_button_,
&QPushButton::clicked,
qApp,
&QApplication::closeAllWindows);
}
界面 ui:
Controller_dialog
0
0
219
83
Dialog
-
-
Start Button
-
Quit
main 文件:
#include
#include "mainwindow.h"
#include "thread_dialog.h"
#include "controller_dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Controller_dialog d;
d.show();
return a.exec();
}
运行结果,打印 Print_thread、Worker 对象的线程号:
可以看到打印结果,Worker 对象在线程 9480,主程序入口在线程 5336