Qt中使用线程之QConcurrent

QConcurrent可以实现并发,好处是我们可以不用单独写一个类了,直接在类里面定义任务函数,然后使用QtConcurrent::run在单独的线程里执行一个任务

1、定义一个任务函数

2、定义1个QFutureWatcher的对象,使用QFutureWatcher来监测任务函数的返回值,其模板参数是任务函数返回值的类型

3、绑定QFutureWatcher的finished信号,通过其result()来获取任务函数运行结束后的返回值;因为任务函数运行结束时QFutureWatcher会发出finished信号

4、调用QtConcurrent::run开启1个单独的线程执行任务函数;该方法返回值为QFuture,其模板参数是任务函数返回值的类型

5、将run()方法的返回值QFuture设置给QFutureWatcher的对象,以便QFutureWatcher的对象能得到任务函数的返回值

举例:

点击开始任务按钮,开启子线程执行任务函数

在任务函数中对num自增,然后发信号给ui线程

ui线程收到信号,更新ui

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QtConcurrent>
#include<QPushButton>
#include<QFuture>
#include<QApplication>
#include<QFutureWatcher>
#include<QLabel>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr): QWidget(parent)
    {
        resize(500,500);

        QPushButton* btn=new QPushButton("开启任务",this);
        btn->setGeometry(10,10,100,50);

        QPushButton* btn2=new QPushButton("停止任务",this);
        btn2->setGeometry(120,10,100,50);
        connect(btn2,&QPushButton::clicked,this,[=](){stop=true;});

        QLabel* lbl=new QLabel(this);
        lbl->setGeometry(10,70,400,100);
        QFont font;
        font.setBold(true);
        font.setPixelSize(15);
        lbl->setFont(font);
        //子线程发出信号,让主线程ui自己来更新
        connect(this,&Widget::labelInfo,this,[=](QString info){
            lbl->setText("num的值:"+info);
        });

        qDebug()<<"UI所在线程的id:"<<QThread::currentThreadId();

        connect(btn,&QPushButton::clicked,this,[=](){

            //槽函数中耗时操作
            //不用单独创建1个类了

            //1、使用QFutureWatcher来监测任务函数的返回值,其模板参数是任务函数返回值的类型
            QFutureWatcher<int>* future_watcher=new QFutureWatcher<int>;

            //2、绑定QFutureWatcher的finished信号,通过其result()来获取任务函数运行结束后的返回值
            //任务函数运行结束时QFutureWatcher会发出finished信号
            connect(future_watcher,&QFutureWatcher<int>::finished,future_watcher,[=](){
                qDebug()<<"返回值是:"<<future_watcher->result();
                future_watcher->deleteLater();
            });

            //3、调用QtConcurrent::run开启1个单独的线程执行任务函数;返回值为QFuture,其模板参数是任务函数返回值的类型
            QFuture<int> future= QtConcurrent::run(&Widget::timeTask,this);
            //4、将future设置给future_watcher,以便future_watcher能得到任务函数的返回值
            future_watcher->setFuture(future);
        });
    }

    ~Widget()=default;

protected:
    void closeEvent(QCloseEvent* ev) override
    {
        stop=true;
    }

    //定义任务函数
    int timeTask()
    {
        qDebug()<<"任务函数所在线程的id:"<<QThread::currentThreadId();
        int index=0;
        while(!stop)
        {
            //向ui线程发出信号,更新label显示的值,要使用QMetaObject::invokeMethod
            QMetaObject::invokeMethod(this,"labelInfo",Qt::QueuedConnection,Q_ARG(QString,QString::number(index++)));
            QThread::msleep(1000);
        }
        return 0;
    }
signals:
    //自定义1个信号,利用这个信号的参数来更新label显示的值
    void labelInfo(QString info);

private:
    //任务函数停止标志
    bool stop=false;
};
#endif // WIDGET_H

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值