Qt Concurrent框架详解(QFuture、QFutureWatcher)

news2025/1/16 5:48:59

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;
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1154493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开关电源绝缘阻抗的检测标准是什么?如何测试绝缘阻抗性能?

绝缘阻抗测试是开关电源测试的一种重要方法&#xff0c;用来检测电气设备接线中断路和线路接触阻抗。用开关电源测试系统测试绝缘阻抗值保证结果准确性&#xff0c;评估绝缘阻抗性能&#xff0c;判断开关电源质量是否良好&#xff0c;从而保证开关电源的稳定性和可靠性。 怎么测…

论文研究中数据获取与查询

数据分析是写论文中一个非常重要的环节&#xff0c;特别是对于与经济相关专业的学子来讲&#xff0c;在写论文时避免不了需要案例分析&#xff0c;这时候数据分析就在其中显得尤为重要。 但是我们通常怎么获取这些数据呢&#xff1f; 下面给大家推荐几个能用得上的数据查询网站…

2023年10月28日历史上的今天大事件早读

1372年10月28日《水浒传》的作者施耐庵逝世 1818年10月28日俄国作家屠格涅夫诞辰 1886年10月28日法国送给美国的自由女神像揭幕 1894年10月28日现代著名作家叶圣陶出生 1902年10月28日马克思第一次被介绍给国人 1940年10月28日意军开始入侵希腊 1945年10月28日赵树理发表…

腾讯新专利,微信聊天终于可以加密/隐藏了!

随着互联网技术的发展&#xff0c;个人信息被倒卖、聊天记录泄露等情况时有发生&#xff0c;让人们不得不警惕慎言。 为了解决这个问题&#xff0c;腾讯最近获得了一项专利&#xff1a;据了解&#xff0c;该项专利名为“聊天消息的显示方法、发送方法、装置、电子设备及介质”。…

亲手教你WebUI自动化框架从零开始搭建

一、设计思路 PO模式 对象库层&#xff1a;二次封装Selenium的方法。 core&#xff1a;主要封装driver方法&#xff0c;并加入日志、失败截图 页面操作层(逻辑层)&#xff1a;元素对象和元素操作的封装。page&#xff1a;封装页面的元素对象和元素操作 业务层&#xff1a;测试…

零信任安全模型和多因素身份验证:提升网络安全的关键一步

近年来&#xff0c;随着疫情的蔓延和科技的飞速发展&#xff0c;数据和工作的数字化程度前所未有。这虽然为机会创造提供了更多空间&#xff0c;但也为潜在威胁行为者提供了新的入侵途径。因此&#xff0c;数据泄露的防范已经成为每个组织IT基础设施中不可或缺的一部分。 数据泄…

为什么SQL日志文件很大,该如何处理?

SQL Server 日志文件是记录所有数据库事务和修改的事务日志文件。用 SQL 术语来说&#xff0c;此日志文件记录对数据库执行的所有INSERT、UPDATE和DELETE查询操作。 如果数据库联机或恢复时日志已满&#xff0c;SQL Server 通常会发出 9002 错误。在这种情况下&#xff0c;数据…

苹果下载神器Folx2024

很多苹果电脑用户日常都会有下载东西的需求&#xff0c;不过Mac系统本身并不自带下载工具&#xff0c;我们只能使用浏览器本身的下载功能进行下载。但是很多时候浏览器的下载功能并不能满足我们的需求&#xff0c;速度也有限。 Folx2024最新版下载如下&#xff1a; https://w…

数据库开发软件Navicat Premium 15 mac中文软件介绍

Navicat Premium 15 mac是一款数据库开发工具&#xff0c;Navicat Premium 15 Mac版可以让你以单一程序同時连接到 MySQL、MariaDB、SQL Server、SQLite、Oracle 和 PostgreSQL 数据库。 Navicat Premium for Mac软件介绍 Navicat premium是一款数据库管理工具。将此工具连接数…

手机怎么去水印?超级好用!

有些图片或视频中带有水印&#xff0c;这些水印可能会影响图片或视频的美观和视觉效果&#xff0c;或者可能会遮盖住部分内容。那么如何利用手机去除图片和视频水印呢&#xff1f;下面分别介绍了一些详细的操作步骤&#xff5e; 方法一&#xff1a;使用醒图APP去除图片水印 1、…

十二、W5100S/W5500+RP2040树莓派Pico<ARP 地址解析>

文章目录 1 前言2 简介2 .1 什么是ARP&#xff1f;2.2 ARP的优点2.3 ARP工作原理2.4 ARP应用场景 3 WIZnet以太网芯片4 ARP网络设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 随着网络安全越来越受到重…

API管理神器:Apipost

在数字化时代&#xff0c;API已成为企业和开发者实现数据互通、应用集成的重要桥梁。然而&#xff0c;随着API数量的不断增加&#xff0c;API设计、调试、文档和测试等工作也变得越来越复杂。为了解决这一痛点&#xff0c;一款名为Apipost的API协同研发工具应运而生&#xff0c…

如何远程访问具有多个显示器的计算机

留出扩展空间对身体和电脑屏幕都有好处。许多人受益于使用多台显示器或将笔记本电脑连接到外接显示器以扩展屏幕。对于使用屏幕的人来说&#xff0c;拥有这样的屏幕空间可能意味着更高效的工作流程和生产力。 但是&#xff0c;如果你需要远程访问那台计算机呢&#xff1f;是否…

containerd-rootless安装

实验环境&#xff1a;centos7.7.1908 参考文档&#xff1a; containerd &#xff08;nerdctl&#xff09; 依赖项 |无根容器 (rootlesscontaine.rs) [CentOS 7] 无法安装 containerd-rootless-setuptool.sh &#xff08;[ERROR] 需要 systemd &#xff08;systemctl --user&…

【Nvidia】nvidia驱动安装

1. 安装前需要安装依赖(必须执行) sudo apt-get update #更新软件列表 #安装编译依赖 sudo apt-get install g sudo apt-get install gcc sudo apt-get install make2. 查看自己的GPU型号 lspci | grep -Ei (vga|display) 或者 lspci | grep -i nvidia 或者 lspci | grep…

控制穆格射流管伺服阀控制器

驱动穆格MOOG伺服阀放大器是一种电子设备&#xff0c;用于驱动伺服阀。它能够将输入信号转换成控制电流来驱动伺服阀力矩马达&#xff0c;从而实现对流量、压力等参数的精确控制。 伺服阀已成为许多自动化系统中不可或缺的一部分。它们被广泛应用于液压和气动系统&#xff0c;…

【React】02.create-react-app基础操作

文章目录 当前以及未来的开发&#xff0c;一定是&#xff1a;组件化开发如何划分组件React的工程化/组件化开发create-react-app基础运用运用react常用版本一个React项目中&#xff0c;默认会安装 2023年最新珠峰React全家桶【react基础-进阶-项目-源码-淘系-面试题】 当前以及…

全球前十正规外盘贵金属理财软件最新排名(综合版)

随着科技的发展和金融市场的繁荣&#xff0c;贵金属理财软件成为了越来越多投资者的首选。为了帮助大家更好地选择合适的贵金属理财软件&#xff0c;本文将结合市场现状&#xff0c;通过功能评测、用户体验、优惠活动、技术安全和合规发展等方面&#xff0c;对全球前十正规外盘…

【网安AIGC专题11.1】将代码生成大模型用于命名实体识别(NER)和关系抽取(RE):提示工程设计+控制变量对比实验(格式一致性、模型忠实度、细粒度性能)

CODEIE: Large Code Generation Models are Better Few-Shot Information Extractors 写在最前面汇报研究背景命名实体识别&#xff08;NER&#xff09;和关系抽取&#xff08;RE&#xff09;相关工作作者动机研究方案实例 研究方案方案预览 实验数据集和基线模型评价指标实验方…

dfs序及相关例题

常用的三种dfs序 欧拉序 每经过一次该点记录一次的序列。 dfs序 记录入栈和出栈的序列。 dfn序 只记录入栈的序列。 dfs序 DFS 序列是指 DFS 调用过程中访问的节点编号的序列。 如何求dfs序&#xff1f;可以用以下代码来找dfs序。 vector<vector<int>> g(n…