Qt Concurrent框架详解(QFuture、QFutureWatcher)

2023-11-01 09:12

本文主要是介绍Qt Concurrent框架详解(QFuture、QFutureWatcher),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.概述

Qt Concurrent是Qt提供的一个并发编程框架,用于简化多线程和并行计算的开发。它提供了一组易于使用的函数和类,可以方便地在多线程环境下处理并发任务。

有以下特点:

简单易用:Qt Concurrent提供了一组高级函数和类,使多线程和并行计算变得简单易用。开发者无需显式地创建和管理线程,而是通过调用Qt Concurrent提供的函数实现并发任务。

自动任务分割:Qt Concurrent能够根据可用的线程数自动将大的问题拆分成更小的任务,并分配给不同的线程并行执行。这样能够最大程度地利用系统资源,提高并发执行效率。

异步计算:Qt Concurrent提供了异步执行任务的机制,可以在后台执行任务,同时不会阻塞主线程,从而提高用户界面的响应性。 主要的类和函数:

  • QFuture:表示一个异步任务的未来结果。可以通过调用QFuture的result()方法来获取结果。还可以使用QFutureWatcher类来监视并处理异步任务的结果。
  • QFutureIterator:用于遍历QFuture所代表的异步任务的结果集合。
  • QThread:Qt Concurrent内部会自动管理线程,不需要手动创建和管理线程。但如果需要更细粒度的控制线程的操作,可以使用QThread类。
  • QtConcurrent::run():用于在后台线程执行函数。它会自动创建一个新的线程,并在该线程中执行指定的函数。
  • QtConcurrent::map():用于并行计算,将一个函数应用于一个容器中的每个元素,并返回结果集。它会根据可用的线程数自动进行任务分割和分配。
  • QtConcurrent::filter():根据指定的谓词函数,在容器中筛选符合条件的元素。也会进行任务分割和分配。
  • QtConcurrent::blockingMapped():与map类似,但是会阻塞当前线程直到所有任务完成。

2.常用方法

在 pro 文件添加“Qt += concurrent”并且在我们的 h 文件添加“#include <QtConcurrent>”,就可以使用这些函数了。基本上所有的 concurrent 函数分为三种类型:

  • run 相关:执行函数用;
  • map 相关:处理容器中的每一项;
  • filter 相关:筛选容器中的每一项。

run方法:创建一个新的线程,并在该线程中执行指定的函数。

  • QFuture<T> run(Function function, ...)
  • QFuture<T> run(QThreadPool *pool, Function function, ...)

map方法:在单独的线程里对容器中的每一项进行操作,并返回结果集。

  • QtConcurrent::map():直接操作容器中的每一项。
  • QtConcurrent::mapped():操作容器中的每一项,将处理结果返回一个新的容器,原容器不变。
  • QtConcurrent::mappedReduced():在 mapped() 的基础上将处理结果进一步传递给一个函数继续处理。

filter方法:filter 相关函数和 map 相关函数类似,也是对容器中的元素进行处理,但 filter 更多侧重筛选元素。

  • QtConcurrent::filter()
  • QtConcurrent::filtered()
  • QtConcurrent::filteredReduced()

3.示例

示例1:将普通函数运行在两个不同的线程中,使用QFuture的result()方法来获取返回结果。

#include <QApplication>
#include <QFuture>
#include <QtConcurrent>QString func1()
{qDebug()<<"我是func1函数";
}
QString func2(QString name)
{qDebug()<<"我是func2函数";return name;
}int main(int argc, char *argv[])
{QCoreApplication  a(argc, argv);//用QFuture获取该函数的运行结果QFuture<QString> fut1 = QtConcurrent::run(func1);//参数2:向func函数传递的参数QFuture<QString> fut2 = QtConcurrent::run(func2, QString("func2"));QString result2 = fut2.result();fut1.waitForFinished();fut2.waitForFinished();qDebug()<<"result2 = "<<result2;return a.exec();
}

运行结果:

示例2: 使用QtConcurrent::map(),QtConcurrent::mapped() ,QtConcurrent::mappedReduced()

map:直接操作容器中的每一项,不返回。

mapped:操作容器中的每一项,将处理结果返回一个新容器,原容器不变。

mappedReduced:mapped() 的基础上将处理结果进一步传递给下一个函数继续处理。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFuture>
#include <QtConcurrent>void processString1(QString& str) {str = str.toUpper();   //转大写
}QString processString2(const QString& str) {// 模拟一些复杂的处理逻辑QThread::msleep(1000);  // 延迟1秒return str.toUpper();   //转大写
}void processString3(QString &result, const QString &intermedia)
{result += " ";result += intermedia;
}MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);QStringList strings1 = {"hello", "world", "qt", "concurrent"};QFuture<void> fut1 = QtConcurrent::map(strings1, processString1);fut1.waitForFinished();qDebug()<<"==========result1=========";for(const QString& result : strings1) {qDebug() << result;}qDebug()<<"==========result1=========";qDebug()<<"==========result2=========";QStringList strings2 = {"hello", "world", "qt", "concurrent"};QFuture<QString> future = QtConcurrent::mapped(strings2, processString2);future.waitForFinished();QList<QString> results = future.results();for(const QString& result : results) {qDebug() << result;}qDebug()<<"==========result2=========";qDebug()<<"==========result3=========";QStringList strings3 = {"hello", "world", "qt", "concurrent"};QFuture<QString> future2 = QtConcurrent::mappedReduced(strings3, processString2,processString3);future2.waitForFinished();QList<QString> results2 = future2.results();for(const QString& results : results2) {qDebug() << results;}qDebug()<<"==========result3=========";
}MainWindow::~MainWindow()
{delete ui;
}

运行结果:

 示例3:使用QFutureWatcher来监视并处理异步任务的结果。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFuture>
#include <QtConcurrent>
#include <QFutureWatcher>QFutureWatcher<QStringList> watcher;QStringList processString(const QStringList& str) {// 模拟一些复杂的处理逻辑QThread::msleep(1000);  // 延迟1秒QStringList ret;for(int i=0;i<str.size();i++){ret.append(str.at(i).toUpper());}return ret;
}MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);QStringList strings = {"hello", "world", "qt", "concurrent"};QFuture<QStringList> future = QtConcurrent::run(processString, strings);watcher.setFuture(future);QObject::connect(&watcher, &QFutureWatcher<void>::finished, this, [&]() {qDebug() << "All tasks finished!";for(const QString& result2 : watcher.result()) {qDebug() << result2;}});QObject::connect(&watcher, &QFutureWatcher<void>::progressValueChanged, [](int value) {qDebug() << "Progress: " << value << "%";});}MainWindow::~MainWindow()
{delete ui;
}

运行结果:

这篇关于Qt Concurrent框架详解(QFuture、QFutureWatcher)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/321980

相关文章

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

SpringBoot3.4配置校验新特性的用法详解

《SpringBoot3.4配置校验新特性的用法详解》SpringBoot3.4对配置校验支持进行了全面升级,这篇文章为大家详细介绍了一下它们的具体使用,文中的示例代码讲解详细,感兴趣的小伙伴可以参考... 目录基本用法示例定义配置类配置 application.yml注入使用嵌套对象与集合元素深度校验开发

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

SpringBoot整合mybatisPlus实现批量插入并获取ID详解

《SpringBoot整合mybatisPlus实现批量插入并获取ID详解》这篇文章主要为大家详细介绍了SpringBoot如何整合mybatisPlus实现批量插入并获取ID,文中的示例代码讲解详细... 目录【1】saveBATch(一万条数据总耗时:2478ms)【2】集合方式foreach(一万条数

Python装饰器之类装饰器详解

《Python装饰器之类装饰器详解》本文将详细介绍Python中类装饰器的概念、使用方法以及应用场景,并通过一个综合详细的例子展示如何使用类装饰器,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. 引言2. 装饰器的基本概念2.1. 函数装饰器复习2.2 类装饰器的定义和使用3. 类装饰

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

Python ZIP文件操作技巧详解

《PythonZIP文件操作技巧详解》在数据处理和系统开发中,ZIP文件操作是开发者必须掌握的核心技能,Python标准库提供的zipfile模块以简洁的API和跨平台特性,成为处理ZIP文件的首选... 目录一、ZIP文件操作基础三板斧1.1 创建压缩包1.2 解压操作1.3 文件遍历与信息获取二、进阶技

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-