Qt实现 在Thread子线程里处理耗时业务

8 篇文章 1 订阅

目录

1、QThread

2、何时使用线程

3、不使用多线程会有什么现象

4、使用线程处理耗时操作

5、线程退出注意点


做应用软件,因为主界面的原因,业务线程可以说​极其重要。如果不开线程的话,软件很难做到流畅,一个卡顿的软件很难被用户买单。

很多初学者会被线程的同步机制给吓到,或者觉得加锁会影响性能,所以干脆会拒绝对线程的使用。

但是合理和高效的使用线程,以及对多线程的掌握程度,往往又决定了软件的性能以及面试的结果和定级​。

因为单纯就应用软件方向而言,如果面试者对线程很陌生,面试官其实也基本可以判定,面试者日常中所负责的只是基础的增删改查业务,而不具备项目的​整体把控能力。

为什么说要掌握线程,​以及线程的同步机制呢。因为很多处理过程,都是耗时的操作,如果都让主线程来处理,软件主界面会不堪重负。

比如用户点击了一个生成报表按钮,如果数据量很大,不是几秒钟就能做好的,这时候用户又点击了另外一个设置按钮,然后设置界面等了​1-2秒才能弹出来,会极大降低​体验。

如果在设计之初,就把可能的耗时任务都放到不同的子线程去处理,处理完毕后,再通过回调或者信号机制通知主线程,就不会影响到主界面​,所以搭建一个稳定、合理的线程池是一件有必要去​做的事情。

如果同步机制做不好,可能就会出现资源抢占、死锁等问题,造成软件卡死​。所以说为了开发出稳定的软件和功能,更需要掌握线程,以及多线程的同步机制​。

幸运的是,很多框架都已经搭建好了现有的线程类或者线程池,如果使用框架,就不需要我们自己去写原生的多线程,提高了开发效率​。

下面一起了解一下如何在qt中,创建子线程处理耗时操作​。

1、QThread

QThread类提供了一种独立于平台的方式来管理线程。一个QThread对象管理一个线程。

子线程在run()函数中开始执行,通过start()启动线程,通过quit()和wait()来退出线程。

2、何时使用线程

当需要处理比较耗时的操作,不希望影响到主界面的操作时,就可以考虑使用线程,来承接那部分耗时的任务,

比如我们在布局上显示4个视频,如果在主线程渲染,那么主界面马上就吃不消了,用户点击操作界面将会十分卡顿。

3、不使用多线程会有什么现象

下面我在主线程模拟了一段耗时的代码,以模拟视频渲染,当点击开始的按钮后,进入耗时操作:

void Form::on_pushButton_clicked()
{
    //模拟解码耗时操作
    int cnt=0;
    while (cnt<50) {
        cnt++;
        qDebug()<<"run main"<<"cnt="<<cnt;
        QThread::msleep(300);
    }
}

界面现象:

这时界面卡主,用户虽然可以操作,但是很卡顿,甚至软件有时候会直接卡死,就需要等耗时循环结束,界面才恢复正常。

但是这往往不是我们希望的效果,于是请出线程,来帮助处理,分担压力。

4、使用线程处理耗时操作

#ifndef WORK_H
#define WORK_H

#include <QObject>
#include <QThread>
#include <QDebug>

class Work:public QThread
{
    Q_OBJECT
public:
    Work():_stop(true)
    {
    }
    ~Work(){
        qDebug()<<"thread start quit";
        _stop = false;
        QThread::quit();
        QThread::wait();
        qDebug()<<"thread success!";
    }

    void run() override
    {
        //模拟解码耗时操作
        int cnt=0;
        while (cnt<50 && _stop) {
            cnt++;
            qDebug()<<"run Thread"<<"cnt="<<cnt;
            QThread::msleep(300);
        }

    }

private:
    bool _stop;
};

#endif // WORK_H

work类继承自QThread,重写父类的QThread的run方法,在run方法中,延时300毫秒,模拟耗时操作。

在btn中启动线程:

void Form::on_pushButton_clicked()
{
    //模拟解码耗时操作
//    int cnt=0;
//    while (cnt<50) {
//        cnt++;
//        qDebug()<<"run main"<<"cnt="<<cnt;
//        QThread::msleep(300);
//    }

    if(_w)
        _w->start();
}

通过调用start()函数,启动子线程,即会调用run方法,进行处理。

界面效果正常:

 

5、线程退出注意点

使用以下,先quit,再wait。

QThread::quit();
QThread::wait();

因为quit()函数虽然是用来停止QThread的,但是由于Qt本身拥有事件循环机制,所以在调用完quit()后,QThread可能还没有停止。

所以在执行quit()后,通常调用wait()来等待QThread子线程的结束,即run函数的结束,这样才能保证在释放QThread的时候,它的子线程是完全停止运行的状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值