(十三)QT的线程

QT实际是有两种线程写法的:
第一种就是常见的写法:继承QThread类,重写run函数,把需要子线程执行的任务放在run函数中,调用start,线程开始执行。
这种写法有个缺点就是:需要线程执行的任务都要放在run函数中,如果你在run中放一个signal,通知run函数外的槽函数执行某个操作,那么这个槽函数就会在主线程中执行即使这个槽函数是在子线程类中的,也会在主线程中执行)。这对于使用信号槽方式的QT来说是无法接受的,因此QT强烈建议大家不要使用这种方式。

另外一种就是QT推荐的moveToThread写法:定义一个继承QObject的类,在类中定义一个槽函数,在槽函数中定义线程需要做的工作。

乍一看,和第一种没啥区别是吧,那么我们让这个槽函数发出一个信号出来,看下结果:
mainwindow.cpp文件:由它启动子线程

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , mThread(new mthread)
{
    ui->setupUi(this);
    
    connect(mThread,&mthread::signal_send,mThread,&mthread::slot_get_send);
    qDebug() << "mainwindow threadID : "<< QThread::currentThread();
    QThread *thread = new QThread;//新建的QThread类
    mThread->moveToThread(thread);//把继承QObject的类moveToThread,放到线程thread中
    thread->start();//调用线程的start方法
    mThread->creatThread();//让子线程发出开始工作的信号
}

mthread.h文件:

#include <QObject>

class mthread : public QObject
{
    Q_OBJECT
public:
    explicit mthread(QObject *parent = nullptr);
    void creatThread();

signals:
    void signal_send();
    void signal_test_signal();
public slots:
    void slot_get_send();
    void slot_test_signal();
};

mthread.cpp文件:

#include "mthread.h"
#include "QThread"
#include "QDebug"

mthread::mthread(QObject *parent) : QObject(parent)
{
    connect(this,&mthread::signal_test_signal,this,&mthread::slot_test_signal);
}

void mthread::creatThread()
{
    emit signal_send();
    qDebug() << "creatThread threadID : "<< QThread::currentThread();
}

void mthread::slot_get_send()
{
    qDebug() << "slot_get_send threadID : "<< QThread::currentThread();
    emit signal_test_signal();
}

void mthread::slot_test_signal()
{
    qDebug() << "slot_test_signal threadID : "<< QThread::currentThread();
}

结果如下:

mainwindow threadID :  QThread(0x230de578580)
creatThread threadID :  QThread(0x230de578580)
slot_get_send threadID :  QThread(0x230e1404ba0)
slot_test_signal threadID :  QThread(0x230e1404ba0)

主线程和子线程中的发出信号的函数都在主线程中,子线程中的两个槽函数都在子线程中运行。

这就告诉我们moveToThread的两个特点:
1.槽函数才是执行子线程工作的地方,千万不要在其他非槽函数的函数中写子线程工作!!(哪怕这些非槽函数就在子线程类中)
2.子线程类中的槽函数都在子线程中运行!

其实QT的线程写法加上它的信号槽,还创建了一个比较方便的工作:可以在一个类中定义很多个任务,然后发出不同的信号,子线程就可以执行不同的槽函数。相比于继承QThread只能执行run()函数中的一个任务,moveToThread的方法中一个线程可以做很多不同的工作。

mainwindow.cpp文件新增:

connect(this,&MainWindow::signal_mainwindow,mThread,&mthread::slot_mainwindows);
//mThread->creatThread();//原来的信号屏蔽掉
emit signal_mainwindow();//mainwindow中增加新的信号signal_mainwindow

mThread.cpp文件新增:

void mthread::slot_mainwindows()
{
    qDebug() << "slot_mainwindows threadID : "<< QThread::currentThread();//新加一个参函数
}

运行结果:

mainwindow threadID :  QThread(0x1af20d1ab90)
slot_mainwindows threadID :  QThread(0x1af20d50c70)

所以总的来说:
1.如果选择——继承QThread类,重写run函数。请把所有需要子线程处理的事务都放在run函数中
2.如果选择——moveToThread。请把所有需要子线程处理的事务都放在槽函数中。(切记!切记!槽函数!)
1)子线程类中的槽函数都在子线程中运行,所以你可以在子线程中任意跳转参函数
2)可以在一个类中定义很多个任务,然后发出不同的信号,子线程就可以执行不同的槽函数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值