往期回顾
【QT进阶】Qt线程与并发之线程和并发的简单介绍-CSDN博客
【QT进阶】Qt线程与并发之QtConcurrent返回值与run方法的参数说明
一、QtConcurrent::run的参数说明
QtConcurrent::run函数的参数类型是模板化的,它可以接受任意可调用对象(函数指针、成员函数指针、函数对象、Lambda表达式等)作为参数。这意味着我们可以传递任何可调用对象作为要在后台线程中执行的任务。
1、QtConcurrent::run函数的签名
template <typename T>
QFuture<T> QtConcurrent::run(T (*functionPointer)(), ...);
这里的T是任务函数的返回类型。我们可以传递一个普通的函数指针,然后在后台线程中执行该函数。除了普通的函数指针外,我们还可以传递其他可调用对象,只要它们符合函数签名的要求即可。
我们看几个参数示例
2、参数示例
QtConcurrent::run函数的参数,可以是全局函数,也可以是类成员函数,还可以是lambda表达式,同时还可以是不带参数的。
1、类成员函数做run参数
intnum1=0;
int num2 = 0;
QFuture<int> future = QtConcrrent::run(this, &MainWindow::timeTask, num1, num2);
2、用全局函数做参数
static int timeTask()
int i= 0;
while(i < 123456789)
{
QFuture<int> future = QtConcurrent::run(timeTask);
i++;
}
return i;
3、lambda表达式做参数
// 在后台线程中执行Lambda表达式
QFuture<int> future = QtConcurrent::run([](){
// 执行一些操作
return result;
});
对比一下,首先run方法里是可以带参数的,其次,如果是用类成员函数做参数,是需要添加this并以类名引导,但是如果是用全局函数做参数,则都不用加,直接放函数名就可以了。
二、获取QtConcurrent的返回值
1、获取方式
获取QtConcurrent的结果,需要使用QFutureWatcher类,链接它的信号finished,然后给watcher设置future,当监控到future执行结束后,可以获取它的执行结果,调用的是result()函数:
qDebug() << "return = " << watcher->result();
2、执行过程
2.1、创建QFutureWatcher对象
创建一个 QFutureWatcher 对象,用于监视 QFuture 对象的执行状态。
QFutureWatcher<int>* fw = new QFutureWatcher<int>;
2.2、执行 成员函数 timeTask
在一个新线程中执行 ch74 类的成员函数 timeTask,并传递 num01 和 num02 作为参数。
QFuture<int> ft = QtConcurrent::run(this, &ch74::timeTask, num01, num02);
2.3、关联QFuture<int> 对象
将 QFuture<int> 对象与 QFutureWatcher 相关联,以便监视其执行状态。
fw->setFuture(ft);
2.4、连接 finished信号
连接 QFutureWatcher 的 finished信号,由于给watcher设置future,当监控到future执行结束后,可以获取它的执行结果,调用的是result()函数:
connect(fw, &QFutureWatcher<int>::finished, [&]{
qDebug() << "QFutureWatcher finished";
qDebug() << "result = " << fw->result();
//qDebug() << "num1 = " << num1;
//qDebug() << "num2 = " << num2;
});
2.5、循环处理事件
通过循环处理事件来保持界面的响应性,直到 QFuture 执行完成。
//没完成的时候循环处理事件来保持界面的响应性
while (!ft.isFinished())
{
QApplication::processEvents(QEventLoop::AllEvents, 30);
}
QApplication::processEvents
函数用于处理事件循环中的事件,确保界面的响应性。调用该函数会处理当前事件队列中的所有事件,直到事件队列为空或者达到指定的最大处理时间。
QEventLoop::AllEvents
参数表示处理所有类型的事件,包括用户输入事件、定时器事件、绘图事件等。
30 参数表示最大处理时间为30毫秒,即函数最多处理30毫秒的事件后返回。这样可以避免在处理事件的过程中阻塞主线程过长时间,确保界面的及时响应。
3、最终代码
#include "ch74.h"
#include <QDebug>
#include <QtConcurrent>
#include <QFuture>
#include <QFutureWatcher>
ch74::ch74(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
ch74::~ch74()
{}
int ch74::timeTask(int& num1, int& num2)
{
for (int i = 0; i < 1000; i++)
{
num1++;
num2++;
qDebug() << num1;
qDebug() << num2;
}
return num1 + num2;
}
void ch74::on_pushButton_clicked()
{
int num01 = 0;
int num02 = 0;
//创建 QFutureWatcher 对象,用于监视一个 QFuture 对象的执行状态
QFutureWatcher<int>* fw = new QFutureWatcher<int>;
//通过 QtConcurrent::run 函数在一个新线程中执行 ch74 类的成员函数 timeTask.(并发)
// num01 和 num02 作为参数传递给 timeTask 函数。
QFuture<int> ft = QtConcurrent::run(this, &ch74::timeTask, num01, num02);
//通过 fw->setFuture(ft) 将 QFuture<int> 对象与 QFutureWatcher 相关联,
//这样 QFutureWatcher 就能监视 QFuture 对象的执行状态
fw->setFuture(ft);
//连接 QFutureWatcher 的 finished 信号,当 QFuture 执行完成时输出调试信息,注意这里由于捕获的是指针fw
//所以lambda表达式里用的是[&]而不是[=]
connect(fw, &QFutureWatcher<int>::finished, [&] {
qDebug() << "QFutureWatcher finished";
qDebug() << "result = " << fw->result();
//qDebug() << "num1 = " << num1;
//qDebug() << "num2 = " << num2;
});
//没完成的时候循环处理事件来保持界面的响应性
while (!ft.isFinished())
{
//QApplication::processEvents 函数用于处理事件循环中的事件,确保界面的响应性
//调用该函数会处理当前事件队列中的所有事件,直到事件队列为空或者达到指定的最大处理时间
QApplication::processEvents(QEventLoop::AllEvents, 30);
}
}
以上就是QtConcurrent返回值与run方法的参数说明的简单介绍
都看到这里了,点个赞再走呗朋友~
加油吧,预祝大家变得更强!