Qt多线程之-moveToThread(附demo)

在最初学习Qt的多线程时,我们往往接触到的是创建一个继承于 QThread 的类,重写run()函数,并使用start()方法间接调用 run() 函数启动线程;从Qt 4.4开始,Qt官方推出了新的线程使用方式,并推荐使用该方式;

直接继承QThread并重写run函数的方式较为方便简洁,缺点是只有run函数运行在子线程,适合单一的任务;
moveToThread的方式必须通过信号槽机制调用函数,相对于继承QThread而言较为复杂,但是所有的函数都运行在子线程中,如何选择还需根据实际需求。

下面对moveToThread的使用进行简单的演示:
1.首先创建一个Qt工程,并添加线程类
右键工程,添加一个继承于 QObject 的类(我这里叫 MoveThread),并在主线程的头文件中添加QThread 和 新类的头文件;

在这里插入图片描述

#include <QThread>
#include "movethread.h"

2.MoveThread 类中添加槽函数

#ifndef MOVETHREAD_H
#define MOVETHREAD_H

#include <QObject>

class MoveThread : public QObject
{
    Q_OBJECT
public:
    explicit MoveThread(QObject *parent = nullptr);

public slots:
    void functionOne();
    void functionTwo();

signals:
};

#endif // MOVETHREAD_H

简单实现,打印当前线程id

#include "movethread.h"
#include <QDebug>
#include <QThread>

MoveThread::MoveThread(QObject *parent) : QObject(parent)
{

}

void MoveThread::functionOne()
{
    qDebug() << "子线程id:" << QThread::currentThread();
}

void MoveThread::functionTwo()
{
    qDebug() << "子线程id:" << QThread::currentThread();
}

3.主线程类中添加成员MoveThread与 QThread 成员(我这里使用指针)

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>
#include "movethread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    QThread *thread;
    MoveThread *moveThread;
};
#endif // WIDGET_H

4.打开设计师界面,添加两个button,用于触发两个槽函数
在这里插入图片描述

5.在主窗口的构造函数中为MoveThread 和QThread 成员申请空间,调用moveToThread,直接启动线程,并打印主线程号,上一步骤中添加的两个按钮分别绑定 MoveThread 中的两个槽函数

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    thread = new QThread(this);
    moveThread = new MoveThread();
    moveThread->moveToThread(thread);
    thread->start();

    qDebug() << "主线程id:" << QThread::currentThread();

    connect(ui->btnFun1, &QPushButton::clicked, moveThread, &MoveThread::functionOne);
    connect(ui->btnFun2, &QPushButton::clicked, moveThread, &MoveThread::functionTwo);
}

注意,此处 thread 指定了父对象,moveThread 不能指定父对象,否则会导致线程方法仍在主线程;
由于MoveThread没有指定父对象,所以不要忘记手动管理内存,在主线程的析构函数中处理

Widget::~Widget()
{
    delete ui;
    if(thread->isRunning())
    {
        thread->quit();
        thread->wait();
    }
    if(moveThread)
    {
        delete moveThread;
        moveThread = nullptr;
    }
}

6.运行,分别点击两个按钮,输出如下
在这里插入图片描述
可以看到, 两个槽函数都运行在子线程。

附完整demo:ThreadDemo

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为啥不吃肉捏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值