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()还在等待其他事件处理,所以主线程不会退出。

相关推荐
BadBadBad__AK12 小时前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境1 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境1 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴2 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
卷无止境4 天前
C++ 的Eigen 库全解析
c++
卷无止境4 天前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端
郝学胜_神的一滴4 天前
CMake 27:缓存变量的特性、语法、类型与实操全解
c++·cmake
Quz5 天前
QML Hello World 入门示例
qt
博客18006 天前
酷宝的使用方法,超好用的免费界面库,C++、MFC可用
c++·mfc·界面库·库来帮·酷宝
郝学胜_神的一滴6 天前
CMake 026:属性体系精讲、四大作用域全解 & 实战代码落地
c++·cmake