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