QT异步编程之QtConcurrent

embedded/2025/3/5 0:08:23/

一、概述

1、QtConcurrent模块提供了一组便捷的函数,用于在不显示创建和管理线程的情况下实现并发编程。

2、它通过将任务提交给线程池来执行,从而避免了频繁创建和销毁线程带来的性能开销。

3、QtConcurrent非常适合处理需要并行执行的批量任务,并且能够自动管理线程和任务的分配。

二、QtConcurrent的核心功能 

1、并行计算:支持对容器(如QList、QVector)中的元素进行并行处理。

(1)QtConcurrent::map()

对容器中的每个元素应用一个函数(原地修改)

 QList list = {1, 2, 3, 4, 5};for (auto value : list)qDebug() << &list << value;auto future = QtConcurrent::map(list, [](int &value) { value *= 2;});future.waitForFinished();for (auto value : list)qDebug() << &list << value;//结果
0xf5949ff688 1
0xf5949ff688 2
0xf5949ff688 3
0xf5949ff688 4
0xf5949ff688 5
0xf5949ff688 2
0xf5949ff688 4
0xf5949ff688 6
0xf5949ff688 8
0xf5949ff688 10

(2)QtConcurrent::mapped()

对容器中的每个元素应用一个函数,并返回一个新的容器 

int convert(int value)
{return value * 2;
}QList<int> list = {1, 2, 3, 4, 5};
for (auto value : list)qDebug() << &list << value;auto future = QtConcurrent::mapped(list, convert);future.waitForFinished();
QList<int> result = future.results();for (auto value : result)qDebug() <<  &result << value;//结果
0xda6f18fbe0 1
0xda6f18fbe0 2
0xda6f18fbe0 3
0xda6f18fbe0 4
0xda6f18fbe0 5
0xda6f18fc08 2
0xda6f18fc08 4
0xda6f18fc08 6
0xda6f18fc08 8
0xda6f18fc08 10

(3)Qt::Concurrent::filter()

过滤容器中的元素(原地修改)

QList<int> list = {1, 2, 3, 4, 5};
for (auto value : list)qDebug() << &list << value;auto future = QtConcurrent::filter(list, [](int value) { return value % 2 == 0;});future.waitForFinished();for (auto value : list)qDebug() << &list << value;//运行结果
0xd8871f9c8 1
0xd8871f9c8 2
0xd8871f9c8 3
0xd8871f9c8 4
0xd8871f9c8 5
0xd8871f9c8 2
0xd8871f9c8 4

2、任务分发:支持将函数或方法分发到线程池中执行

(1)QtConcurrent::run()

将函数分发到线程池中执行,不会阻塞当前线程;

返回一个QFuture对象,用于获取任务的执行结果或监视任务状态

支持普通函数、Lambda表达式、成员函数等多种调用方式

int add(int a, int b)
{qDebug() << "Task running in thread" << QThread::currentThreadId();return a + b;
}void print()
{QThread::sleep(2);qDebug() << "Task print in thread" << QThread::currentThreadId();
}class MyClass
{
public:void function(){qDebug() << "Task function in thread" << QThread::currentThreadId();}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);qDebug() << "start";//无参调用QtConcurrent::run(print);//有参调用QtConcurrent::run(add, 3, 4);//Lambda表达式QtConcurrent::run([](int a, int b){qDebug() << "Task Lambda in thread" << QThread::currentThreadId();return a + b;}, 2, 3);//成员函数MyClass test;QtConcurrent::run(&test, &MyClass::function);qDebug() << "end";return a.exec();
}//结果
start
end
Task function in thread 0x6c38
Task running in thread 0x8fd0
Task print in thread 0x4a28

3、异步编程:支持异步执行任务,并通过信号与槽机制通知任务完成

(1)QFuture:QFuture的结果查询函数,都是阻塞型的,会等待QtConcurrent::run()结束

表示异步计算的结果,可以通过result()或results()获取计算结果,支持等待任务完成(waitForFinished());

int getCount(int n)
{int i = 0;while (i < n){qDebug() << i;QThread::sleep(1);++i;}
}
int main(int argc, char *argv[])
{QApplication a(argc, argv);qDebug() << "start";QFuture<int> future = QtConcurrent::run(getCount, 4);qDebug() << future.result() << future.resultCount();  //会阻塞线程qDebug() << "end";return a.exec();
}//结果
start
0
1
2
3
-1 1
end

(2)QFutureWatcher:用于监视QFuture的状态,通过信号与槽机制通知任务完成、进度更新等 

QFuture类本身未继承QObject,所以没法直接使用信号槽,所以需要另一个监视类QFutureWatcher。

int getCount(int n)
{int i = 0;while (i < n){qDebug() << i;QThread::sleep(1);++i;}return -1;
}int main(int argc, char *argv[])
{QApplication a(argc, argv);qDebug() << "start";QFuture<int> future = QtConcurrent::run(getCount, 4);QFutureWatcher<int> watcher;watcher.setFuture(future);QObject::connect(&watcher, &QFutureWatcher<int>::finished, [&](){qDebug() << QThread::currentThreadId() << future.result() << future.resultCount();});qDebug() << "end";return a.exec();
}//结果
start
0
QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race
end
1
2
3
0x8818 -1 1


http://www.ppmy.cn/embedded/169702.html

相关文章

Java 泛型(Generics)详解与使用

一、什么是 Java 泛型&#xff1f; 泛型&#xff08;Generics&#xff09;是 Java 1.5 引入的一项重要特性&#xff0c;主要用于 类型参数化&#xff0c;允许在类、接口和方法定义时使用 类型参数&#xff08;Type Parameter&#xff09;&#xff0c;从而提高代码的复用性、类…

java2025热点面试题之springmvc

1. 请解释Spring MVC的工作原理。 答案&#xff1a; Spring MVC是一个基于Java的MVC框架&#xff0c;用于构建Web应用程序。其工作原理如下&#xff1a; 客户端发送请求到DispatcherServlet&#xff0c;它是Spring MVC的前端控制器。DispatcherServlet查询HandlerMapping&…

Spock框架:让单元测试更优雅的高效武器

&#x1f4d6; 前言&#xff1a;为什么选择Spock&#xff1f; 在软件开发领域&#xff0c;单元测试是保证代码质量的基石。但传统的JUnit/TestNG测试框架在面对复杂测试场景时&#xff0c;往往会显得力不从心。Spock框架作为新一代测试框架的佼佼者&#xff0c;以其独特的BDD&…

基于SpringBoot+Vue的医院挂号管理系统+LW示例参考

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

Spring Boot 使用过滤器filter

执行流程 在Spring Boot项目中&#xff0c;过滤器&#xff08;Filter&#xff09;的执行流程遵循Servlet规范。具体来说&#xff0c;过滤器是在请求到达目标资源之前和响应返回给客户端之前执行的一系列操作。下面是详细的过滤器执行流程&#xff1a; 初始化阶段: 当Web应用启…

前端面试题最新版

一、Vue 相关 1. 基础题 Vue 2 和 Vue 3 的主要区别是什么&#xff1f; 答案&#xff1a; 响应式系统&#xff1a;Vue 2 使用 Object.defineProperty&#xff0c;Vue 3 使用 Proxy。Composition API&#xff1a;Vue 3 引入了 Composition API&#xff0c;提供了更好的逻辑复用…

CSS隐藏元素的方式

方式一&#xff1a; visibility 属性 visibility 属性默认值是 show &#xff0c;如果设置为 hidden &#xff0c;元素会隐藏。 元素看不见了&#xff0c;还占有原来的位置&#xff08;元素的大小依然保持&#xff09;。 方式二&#xff1a; display 属性 设置 dis…

C语言实现单链表

单链表是数据结构中最基础的链式结构,它不按照线性的顺序存储数据,而是由若干个同一结构类型的“节点”依次串联而成的,即每一个节点里保存着下一个节点的地址(指针)。 上图中,一个表头变量head是用来存储链表首节点的地址,链表中每个节点有data(数据)部分和n…