QtConcurrent和QFuture的使用

        在Qt中,有时候我们会遇到这样一种情况,需要执行一个很长时间的操作,这时候我们的主界面就会卡住。我们的通常做法就是把这个很长时间的操作扔到线程里去处理,可以使用标准库中的线程也可以使用QThread。

        如果我们要在这个很长时间的操作之后,在UI上显示一些东西,或者改变一些UI上的控件的状态。这种时候标准库的线程就不是很好用了,通常这种时候我们会使用QThread,创建一个新的类继承QObject,然后再这个新的类里面写一堆信号和槽,和主线程通讯传递消息改变UI界面。但是这种太麻烦了,每次都要新创建一个类和一堆信号,十分不好管理。

        在查了资料后,我发现了Qt有提供专门并发的类QtConcurrent,以及接收异步计算结果的QFuture类。在这里记录一下QtConcurrent和QFuture的使用。


介绍:

        Concurrent是并发的意思,而QtConcurrent同std一样,是一个命名空间(namespace),想使用它需要先在Project工程文件中导入模块,并包含头文件QtConcurrent/QtConcurrent。

QT += concurrent#include <QtConcurrent/QtConcurrent>

        QtConcurrent提供了一些高级的 API,使得在编写多线程的时候,无需使用低级线程原语,如读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器内核数自动调整使用的线程数。

        QtConcurrent中使用最多的是它的run()函数,每调用一次QtConcurrent::run()函数,就会新建立一个线程运行我们让它执行的函数。run()函数的返回值QFuture类型的,run()函数是有很多重载,这里就简单讲几个常用的。


QtConcurrent::run示例:

调用全局函数: 

函数原型:
QFuture<T> QtConcurrent::run(Function func, ...)

#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QDebug>
#include <QThread>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
}QString func(QString content)
{QString str = QString("%1 %2 %3.").arg(__FUNCTION__).arg(content).arg(quintptr(QThread::currentThreadId()));return str;
}void MainWindow::on_pushButton_clicked()
{QFuture<QString> fut1 = QtConcurrent::run(func, QString("Thread_1"));// 用QFuture获取该函数的运行结果,参数2:向func函数传递的参数QFuture<QString> fut2 = QtConcurrent::run(func, QString("Thread_2"));QString result1 = fut1.result();QString result2 = fut2.result();qDebug() << result1;qDebug() << result2;fut1.waitForFinished();// waitForFinished()保证线程执行完毕fut2.waitForFinished();
}

        这里使用QFuture的result()函数获取QtConcurrent::run()执行的函数的返回值,然后打印出来,打印结果如下:

调用匿名函数: 

         上面的示例中的func也可以改成匿名函数,只是写法上不同,结果都是一样的:

QFuture <QString> future =  QtConcurrent::run([=](){QString str = QString("%1 %2 %3.").arg(__FUNCTION__).arg("Thread_1").arg(quintptr(QThread::currentThreadId()));return str;
});
QFuture <QString> future2 = QtConcurrent::run([=](){QString str = QString("%1 %2 %3.").arg(__FUNCTION__).arg("Thread_2").arg(quintptr(QThread::currentThreadId()));return str;
});

 调用成员函数:

         同样的,QtConcurrent::run()也可以调用成员函数,第一个参数必须是一个const引用或一个指向该类实例的指针,第二个参数是函数指针:

QString MainWindow::func(QString content)
{QString str = QString("%1 %2 %3.").arg(__FUNCTION__).arg(content).arg(quintptr(QThread::currentThreadId()));return str;
}QFuture<QString> fut1 = QtConcurrent::run(this, &MainWindow::func, QString("Thread_1"));
QFuture<QString> fut2 = QtConcurrent::run(this, &MainWindow::func, QString("Thread_2"));

调用其他类的成员函数: 

         调用其他类的成员函数,包括Qt提供的函数也是同样的方法:

QByteArray bytearray = "hello,world";
QFuture<QList<QByteArray>> future = QtConcurrent::run(bytearray, &QByteArray::split, ',');

 使用线程池中的线程调用函数:

// 函数原型

template <typename T> QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)


使用QFutureWatcher监视线程:

        QFuture 表示异步计算的结果,QFutureWatcher 则允许使用信号和槽监视 QFuture,也就是说,QFutureWatcher 是为 QFuture 而生的。

        示例,开始计算并当完成时通过槽获取结果:

// 实例化对象,并连接槽到 finished() 信号,等线程中函数完成后就会触发连接的槽。
MyClass myObject;
QFutureWatcher<int> watcher;
connect(&watcher, &QFutureWatcher<QVector<complex<double>>>::finished, &myObject, &MyClass::handleFinished);// 开始计算
QFuture<int> future = QtConcurrent::run(...);
watcher.setFuture(future);

        匿名函数的写法:

QFutureWatcher<QVector<complex<double>>>* pwatcher = new QFutureWatcher<QVector<complex<double>>>;
QFuture<QVector<complex<double>>> future = QtConcurrent::run([=]() {QVector<complex<double>> result;// 费时操作在这里执行,之后返回QVector<complex<double>>类型的结果return result;
});
connect(pwatcher, &QFutureWatcher<QVector<complex<double>>>::finished, this, [=]() {// 使用pwatcher->result()获取在QtConcurrent::run()中的返回值QVector<complex<double>> img2result = pwatcher->result();// 执行费时操作完成之后的操作,例如改变UI界面的控件
});
pwatcher->setFuture(future);

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT 随机动态可视化图表分析

动态可视化图表分析实例如下图: 这样的动态可视化图表可以使用ChatGPT OpenAI 来实现。 给ChatGPT发送指令: 你现在是一个数据分析师,请使用HTML,JS,Echarts,来完成一个动态条形图,条形图方向横向,数据可以随机生成,并且随机生成10个不同的商品名称,每个类别分别用…

Nginx到底是什么,他能干什么?

目录 Ngnix是什么&#xff0c;它是用来做什么的呢&#xff1f; 一。Nginx简介 二&#xff0c;为什么要用Nginx呢&#xff1f; 二。Nginx应用 1.HTTP代理和反向代理 2.负载均衡 Ngnix是什么&#xff0c;它是用来做什么的呢&#xff1f; 一。Nginx简介 Nginx是enginex的简写&…

基于大语言模型知识问答应用落地实践 – 知识库构建(下)

上篇介绍了构建知识库的大体流程和一些优化经验细节&#xff0c;但并没有结合一个具体的场景给出更细节的实战经验以及相关的一些 benchmark 等&#xff0c;所以本文将会切入到一个具体场景进行讨论。 目标场景&#xff1a;对于 PubMed 医疗学术数据中的 1w 篇文章进行知识库构…

Mycat之前世今生

如果我有一个32核心的服务器&#xff0c;我就可以实现1个亿的数据分片&#xff0c;我有32核心的服务器么&#xff1f;没有&#xff0c;所以我至今无法实现1个亿的数据分片。——MyCAT ‘s Plan 话说“每一个成功的男人背后都有一个女人”&#xff0c;自然MyCAT也逃脱不了这个诅…

C语言每日一练------Day(6)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;整数转换 异或 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn…

ChatGPT⼊门到精通(2):ChatGPT 能为我们做什么

⼀、雇佣免费的⼲活⼩弟 有了ChatGPT后&#xff0c;就好⽐你有了好⼏个帮你免费打⼯的「⼩弟」&#xff0c;他们可以帮你做很多 ⼯作。我简单总结⼀些我⽬前使⽤过的⽐较好的基于ChatGPT的服务和应⽤。 1、总结、分析 当我们在阅读⼀些⽂章和新闻的时候&#xff0c;有的⽂章写…

ARM-M0 + 24bit 高精度ADC,采样率4KSPS,国产新品,传感器首选

ARM-M0内核MCU 内置24bit ADC &#xff0c;采样率4KSPS flash 64KB&#xff0c;SRAM 32KB 适用于传感器&#xff0c;电子秤&#xff0c;体脂秤等等

同源策略与解决方法

同源策略与解决方法 1.浏览器的同源策略 1.1 同源策略 同源策略&#xff08;same origin policy&#xff09;&#xff0c;一种安全策略&#xff0c;用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。 浏览器默认两个不同的源之间是可以互相访问资源和…

集合框架-(Collection/Map)

1.单列集合 1.1基础概要 集合中存储的是对象的地址信息&#xff0c;想要输出对象的信息&#xff0c;需要在具体的类中重写toString&#xff08;&#xff09;方法 Collection代表单列集合&#xff0c;每个元素数据只包含一个值 List集合&#xff1a;添加的元素可以是有序、可…

【第1章 数据结构概述】

目录 一. 基本概念 1. 数据、数据元素、数据对象 2. 数据结构 二. 数据结构的分类 1. 数据的逻辑结构可分为两大类&#xff1a;a. 线性结构&#xff1b;b. 非线性结构 2. 数据的存储结构取决于四种基本的存储方法&#xff1a;顺序存储、链接存储、索引存储、散列存储 3. …

uni-app中使用iconfont彩色图标

uni-app中使用iconfont彩色图标 大家好&#xff0c;今天我们来学习一下uni-app中使用iconfont彩色图标&#xff0c;好好看&#xff0c;好好学&#xff0c;超详细的 第一步 首先&#xff0c;从iconfont官网&#xff08;iconfont-阿里巴巴矢量图标库&#xff09;选择自己需要的图…

从零构建深度学习推理框架-11 Resnet

op和layer结构 在runtime_ir.cpp中&#xff0c;我们上一节只构建了input和output&#xff0c;对于中间layer的具体实现一直没有完成&#xff1a; for (const auto& kOperator : this->operators_) {if (kOperator->type "pnnx.Input") {this->input_o…

Soul涉赌?元宇宙“皮囊”绷不住走样的“灵魂社交”

“软色情”、“杀猪盘”之后&#xff0c;陌生人社交平台Soul又多了一张“涉赌”标签。 8月初&#xff0c;视频媒体青蜂侠Bee报道称&#xff0c;Soul平台内游戏“星际庄园”名为“种地”&#xff0c;但用户充值种“水果”、平台发起概率抽奖、奖励转手可场外变现的玩法暗藏赌博…

DNS 协议都没听过?你配做开发?

一、什么是DNS协议&#xff1f; DNS协议是一种用于将域名转换为IP地址的分布式命名系统。它通过将用户提供的域名映射到相应的IP地址&#xff0c;实现了互联网上资源的定位和访问。DNS协议采用了层次化的域名结构&#xff0c;使得域名之间可以建立逻辑上的关联。 二、DNS解析过…

新建Spring Boot项目

使用IDEA 来创建: 文件-新建-项目 填写项目元数据 选择依赖项 此处可以先选 web-spring web 关于这些依赖项&#xff0c;更多可参考&#xff1a; IDEA创建Spring boot项目时各依赖的说明&#xff08;Developer Tools篇&#xff09;[1] 项目结构介绍 展开项目&#xff0c;此时…

跨站请求伪造(CSRF)

文章目录 渗透测试漏洞原理跨站请求伪造&#xff08;CSRF&#xff09;1. CSRF概述1.1 基本概念1.1.1 关键点1.1.2 目标 1.2 CSRF场景1.2.1 银行账户转账1.2.2 构造虚假网站1.2.3 场景建模1.2.4 实验 1.3 CSRF类别1.3.1 POST方式 1.4 CSRF验证1.4.1 CSRF Poc generator 1.5 XSS与…

Python爬虫(十六)_JSON模块与JsonPath

数据提取之JSON与JsonPATH JSON(JavaScript Object Notation)是一种轻量级的数据交换格式&#xff0c;它是的人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景&#xff0c;比如网站前台与后台之间的数据交互。 JSON和XML的比较可谓不相…

Day50|动态规划part11:188.买卖股票的最佳时机IV、123. 买卖股票的最佳时机III

188. 买卖股票的最佳时机IV leetcode链接&#xff1a;188 题「买卖股票的最佳时机 IVopen in new window」 视频链接&#xff1a;动态规划来决定最佳时机&#xff0c;至多可以买卖K次&#xff01;| LeetCode&#xff1a;188.买卖股票最佳时机4 给你一个整数数组 prices 和一…

用反射实现自定义Java对象转化为json工具类

传入一个object类型的对象获取该对象的class类getFields方法获取该类的所有属性对属性进行遍历&#xff0c;并且拼接成Json格式的字符串&#xff0c;注意&#xff1a;通过属性名来推断方法名获取Method实例通过invoke方法调用 public static String objectToJsonUtil(Object o…

线程安全-搞清synchronized的真面目

多线程编程中&#xff0c;最难的地方&#xff0c;也是最重要的一个地方&#xff0c;还是一个最容易出错的地方&#xff0c;更是一个特别爱考的地方&#xff0c;就是线程安全问题。 万恶之源&#xff0c;罪魁祸首&#xff0c;多线程的抢占式执行,带来的随机性. 如果没有多线程,此…