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

相关推荐
青春:一叶知秋19 小时前
【C++】protobuf序列化与反序列化
开发语言·c++
Zhang~Ling20 小时前
C++ 红黑树封装:myset和mymap的底层实现
开发语言·数据结构·c++·算法
啦啦啦啦啦zzzz20 小时前
数据结构:堆排序
数据结构·c++·
原来是猿20 小时前
为什么 C++ 需要区分左值和右值?
开发语言·c++
珊瑚里的鱼21 小时前
C++的强制类型转换
android·开发语言·c++
星恒随风21 小时前
C++ 类和对象入门(二):默认成员函数、构造函数和析构函数详解
开发语言·c++·笔记·学习
一个不知名程序员www21 小时前
算法学习入门---算法题DAY5
c++·算法
牛油果子哥q21 小时前
【C++ this指针】C++ this指针深度精讲:this底层本质、存储位置、调用机制、const this指针、空指针调用、面试坑点与工程实战
开发语言·c++·面试
坚果派·白晓明21 小时前
[鸿蒙PC三方库移植适配] 使用 AtomCode + Skills 自动完成spdlog鸿蒙化适配
c++·华为·ai编程·harmonyos·skills·atomcode
小禹在努力21 小时前
brpc1.15问题实录:bthread_worker_count取Node CPU,K8s缩容引发线程数超限
c++·微服务·rpc