51、Move方式创建线程---------多线程

Move方式创建线程

这种方法通过将工作逻辑封装在一个 QObject 派生类中,并将其移动到 QThread 对象中执行。通过信号和槽实现线程间通信。移动过后任务类归属于QThread子线程。

QObject移动到线程的方法

cpp 复制代码
void QObject::moveToThread(QThread *targetThread)

优点:

  • 更加符合 Qt 的信号槽机制。
  • 更容易管理线程生命周期。
  • 提高代码的可维护性和可扩展性。

我们先实现一个自定义的Worker任务类,使其继承自QObject,但是要注意,类的声明一定要包含Q_OBJECT宏

cpp 复制代码
class Worker : public QObject
{
    Q_OBJECT
public:
    //显示构造worker类
    explicit Worker(QObject *parent = nullptr);
signals:

public slots:
    //响应线程started信号
    void doWork();
signals:
    //任务完成后发出这个信号
    void finished();
};

实现构造函数

cpp 复制代码
Worker::Worker(QObject *parent) : QObject(parent)
{

}

实现开始任务的槽函数

cpp 复制代码
void Worker::doWork()
{
    qDebug() << "工作线程开始:" << QThread::currentThreadId();
    for(int i = 0; i < 5; i++){
        qDebug() << "计数:" << i;
        QThread::sleep(1); // 模拟耗时操作
    }
    //发送结束信号
    emit finished();
    qDebug() << "工作线程结束:" << QThread::currentThreadId();
}

在主函数中创建一个线程,并且将这个任务类移交给线程

注意

被移交的类一定不能有父窗口

cpp 复制代码
    //创建一个新的线程
    QThread* worker_thread = new QThread();
    //创建任务类
    Worker* worker = new Worker();

    //将worker移动到线程里
    worker->moveToThread(worker_thread);

因为我们要通过线程的信号通知任务类开始工作,以及任务类要通过完成信号通知线程退出等,这里先列举几个信号

QThread线程开始信号,该信号在调用QThread的start()方法后由QThread发出

cpp 复制代码
[signal] void QThread::started()

QThread线程结束信号,在线程调用quit()或者正常退出时发出这个信号

cpp 复制代码
[signal] void QThread::finished()

我们先捕获线程的开始信号, 因为连接信号不是在QObject类里,所以显示调用QObject作用域连接

cpp 复制代码
//连接线程开始信号
QObject::connect(worker_thread,&QThread::started,worker,&Worker::doWork);

所有QObject都有一个deleteLater槽函数

cpp 复制代码
[slot] void QObject::deleteLater()

捕获线程退出信号,连接线程自己的deleteLater槽函数,

cpp 复制代码
//连接线程退出信号和回收槽函数
QObject::connect(worker_thread, &QThread::finished, worker_thread, &QThread::deleteLater);

连接worker退出信号和回收槽函数

cpp 复制代码
//连接worker退出信号和回收槽函数
QObject::connect(worker,&Worker::finished,worker,&Worker::deleteLater);

启动线程

cpp 复制代码
//启动线程
worker_thread->start();

完整版代码

cpp 复制代码
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    //创建一个新的线程
    QThread* worker_thread = new QThread();
    //创建任务类
    Worker* worker = new Worker();

    //将worker移动到线程里
    worker->moveToThread(worker_thread);

    //连接线程开始信号
    QObject::connect(worker_thread,&QThread::started,worker,&Worker::doWork);

    //连接任务类结束信号,调用线程退出信号
    QObject::connect(worker,&Worker::finished, worker_thread, &QThread::quit);

    //连接线程退出信号和回收槽函数
    QObject::connect(worker_thread, &QThread::finished, worker_thread, &QThread::deleteLater);

    //连接worker退出信号和回收槽函数
    QObject::connect(worker,&Worker::finished,worker,&Worker::deleteLater);

    //启动线程
    worker_thread->start();
    MainWindow mainwindow;
    mainwindow.show();
    //等待任务执行完成退出
    return a.exec();
}

程序运行后,输出

bash 复制代码
工作线程开始: 0x4124
计数: 0
计数: 1
计数: 2
计数: 3
计数: 4
工作线程结束: 0x4124

因为a.exec()还在等待其他事件处理,所以主线程不会退出。

相关推荐
汉克老师4 小时前
GESP2026年9月认证C++六级( 第三部分编程题(1、数组划分))精讲
c++·gesp·小学生·学c++编程
千里码aicood5 小时前
基于PLC与机器视觉的智能分拣控制系统设计
c++·自动化·plc
漂流瓶jz5 小时前
UVA-1442 洞穴 题解答案代码 算法竞赛入门经典第二版
c++·算法·题解·aoapc·算法竞赛入门经典·uva
朽棘不雕5 小时前
进一步了解模板
c++
汉克老师8 小时前
CSP-J 2026 初赛试题解析(第一部分:选择题(8-15))精讲
c++·csp-j·小学生·学c++编程
wabs6669 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
风合星语10 小时前
2026 ROS 2 Lyrical C++ 入门(五):Action 实战——任务反馈、取消与超时处理
c++·机器人·ros2·异步编程·lyrical
91刘仁德10 小时前
C++ 继承和多态 设计模式
c语言·c++·笔记
库玛西11 小时前
哈夫曼树与前缀编码:数据压缩的贪心核心
c语言·c++·笔记·考研
别动我齐刘海11 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人