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_OBJECTpublic: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显示的值emit labelInfo(QString::number(index++));QThread::msleep(1000);}return 0;}
signals://自定义1个信号,利用这个信号的参数来更新label显示的值void labelInfo(QString info);private://任务函数停止标志bool stop=false;
};
#endif // WIDGET_H