QtConcurrent和QFuture的使用

这篇具有很好参考价值的文章主要介绍了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()执行的函数的返回值,然后打印出来,打印结果如下:

QtConcurrent和QFuture的使用,QT,QtConcurrent,Qt多线程

调用匿名函数: 

         上面的示例中的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);

        匿名函数的写法:文章来源地址https://www.toymoban.com/news/detail-681419.html

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

到了这里,关于QtConcurrent和QFuture的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Qt 中多线程的使用

    在进行桌面应用程序开发的时候, 假设应用程序在某些情况下需要处理比较复杂的逻辑, 如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使用多线程,其中一个线程处理窗口事件,其他线程进行逻辑运算,多个线程各司其职,不

    2024年02月03日
    浏览(10)
  • Qt 中线程池的使用

    Qt 中线程池的使用

    我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。 那么有没有一种办

    2024年02月11日
    浏览(9)
  • Qt线程池QThreadPool使用示例

    Qt线程池QThreadPool使用示例

    前言 线程池顾名思义就是同时管理多个线程的\\\"池子\\\",它是一种并发处理技术,在程序中使用线程池能够提高线程的使用效率,提高程序的稳定性。 本文从线程池的实现原理开始,介绍了QT框架里的线程池QThreadPool,并提供一个使用示例。 1.线程池原理介绍 线程池的实现思路

    2024年02月07日
    浏览(11)
  • Qt多线程使用的两种方式

    方式1 :继承自QThread类,重载run函数。此实现方法只有run()函数内的代码是运行在子线程内。 (不使用事件循环) 使用方法 : (1)run函数内有一个while或for的死循环(模拟耗时操作); (2)通过一个 标记位 来控制死循环的退出; (3)run()函数中无限循环记得 强制休息

    2023年04月10日
    浏览(15)
  • 【调试记录】QT中使用多线程导致的死锁

    原因在于第18行采用阻塞队列的连接方式。 子线程在第17行获取到锁,主线程刚好运行到24行准备获取锁。此时子线程执行第18行,阻塞调用等待主线程执行 qDebug() \\\"invokeMethod:\\\" ++count_; 完成。 子线程已经获取到锁,主线程等待获取锁,子线程又等待主线程事件循环执行函数,由

    2023年04月16日
    浏览(8)
  • Qt使用OpenGL进行多线程离屏渲染

    Qt使用OpenGL进行多线程离屏渲染

    基于Qt Widgets的Qt程序,控件的刷新默认状况下都是在UI线程中依次进行的,换言之,各个控件的QWidget::paintEvent方法会在UI线程中串行地被调用。若是某个控件的paintEvent很是耗时(等待数据时间+CPU处理时间+GPU渲染时间),会致使刷新帧率降低,界面的响应速度变慢。 假如这个

    2024年02月02日
    浏览(10)
  • PyQt应用程序中的多线程:使用Qt还是Python线程?

    PyQt应用程序中的多线程:使用Qt还是Python线程?

    多线程模块能够更加高效得完成任务,但是在PyQt 应用程序中实现多线程可以使用 Qt 的线程模块(QThread)或者 Python 的 threading 模块。两者各有优劣,具体选择取决于项目需求和个人偏好。下面我们将以案例来说明两种模块具体得优缺点。 1、问题背景 在 PyQt 应用程序中,编

    2024年02月22日
    浏览(13)
  • 在QT中使用多线程并发服务器(C++)

    在QT中使用多线程并发服务器(C++)

    什么是多线程并发服务器?在QT里如何使用多线程并发服务器呢? 多线程并发服务器是一种网络服务器设计,它能够同时处理多个客户端的请求。在多线程服务器中,主线程负责监听和接受来自客户端的连接请求,每当有一个新的连接请求到来时,服务器就会创建一个新的线

    2024年04月11日
    浏览(10)
  • 【QT】C++和QML使用多线程优化界面切换卡顿的方法

    【QT】C++和QML使用多线程优化界面切换卡顿的方法

    qt提供了一种声明式语言qml,可以使用一些可视组件以及这些组件之间的交互来描述用户界面,而c++可以只负责后台逻辑的处理,将界面和后台分离开来,由qml来做UI界面,c++负责后端处理,对我个人来说,这样的方式大大的方便了对界面和逻辑的修改和维护; 由于UI界面是工

    2024年01月19日
    浏览(10)
  • 【QT5-自我学习-线程qThread练习-两种使用方式-1:通过继承线程类来使用-基础样例】

    【QT5-自我学习-线程qThread练习-两种使用方式-1:通过继承线程类来使用-基础样例】

    学习线程其实有一段时间了,当时只是学习,没有实际用起来,最近做的一个qt程序,发现如果不使用线程,那么就会导致界面卡死,这样才体现出线程的实际作用。 发现卡顿的程序就是前几天说到的“【QT调用ST-link-使用QT编写程序-调用ST-LINK_CLI.exe-烧写STM32F4xxx-基础样例】”

    2024年02月11日
    浏览(19)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包