• 【QT进阶】Qt线程与并发之QtConcurrent返回值与run方法的参数说明


    往期回顾

    【QT进阶】Qt线程与并发之线程和并发的简单介绍-CSDN博客

    【QT进阶】Qt线程与并发之创建线程的三种方法(超详细介绍)-CSDN博客

    【QT进阶】Qt线程与并发之QtConcurrent的简单介绍-CSDN博客

     【QT进阶】Qt线程与并发之QtConcurrent返回值与run方法的参数说明

    一、QtConcurrent::run的参数说明

    QtConcurrent::run函数的参数类型是模板化的,它可以接受任意可调用对象(函数指针、成员函数指针、函数对象、Lambda表达式等)作为参数。这意味着我们可以传递任何可调用对象作为要在后台线程中执行的任务。

    1、QtConcurrent::run函数的签名

    1. template <typename T>
    2. QFuture<T> QtConcurrent::run(T (*functionPointer)(), ...);

    这里的T是任务函数的返回类型。我们可以传递一个普通的函数指针,然后在后台线程中执行该函数。除了普通的函数指针外,我们还可以传递其他可调用对象,只要它们符合函数签名的要求即可。

    我们看几个参数示例

     2、参数示例

    QtConcurrent::run函数的参数,可以是全局函数,也可以是类成员函数,还可以是lambda表达式,同时还可以是不带参数的。

    1、类成员函数做run参数

    1. intnum1=0;
    2. int num2 = 0;
    3. QFuture<int> future = QtConcrrent::run(this, &MainWindow::timeTask, num1, num2);

    2、用全局函数做参数 

    1. static int timeTask()
    2. int i= 0;
    3. while(i < 123456789)
    4. {
    5. QFuture<int> future = QtConcurrent::run(timeTask);
    6. i++;
    7. }
    8. return i;

    3、lambda表达式做参数 

    1. // 在后台线程中执行Lambda表达式
    2. QFuture<int> future = QtConcurrent::run([](){
    3. // 执行一些操作
    4. return result;
    5. });

    对比一下,首先run方法里是可以带参数的,其次,如果是用类成员函数做参数,是需要添加this并以类名引导,但是如果是用全局函数做参数,则都不用加,直接放函数名就可以了。

    二、获取QtConcurrent的返回值 

    1、获取方式

    获取QtConcurrent的结果,需要使用QFutureWatcher类,链接它的信号finished,然后给watcher设置future,当监控到future执行结束后,可以获取它的执行结果,调用的是result()函数:

    qDebug() << "return = " << watcher->result();

    2、执行过程

     2.1、创建QFutureWatcher对象

    创建一个 QFutureWatcher 对象,用于监视 QFuture 对象的执行状态。

        QFutureWatcher<int>* fw = new QFutureWatcher<int>;
    2.2、执行 成员函数 timeTask

    在一个新线程中执行 ch74 类的成员函数 timeTask,并传递 num01 和 num02 作为参数。 

        QFuture<int> ft = QtConcurrent::run(this, &ch74::timeTask, num01, num02);
    2.3、关联QFuture 对象

    将 QFuture 对象与 QFutureWatcher 相关联,以便监视其执行状态。 

    fw->setFuture(ft);
    2.4、连接 finished信号

    连接 QFutureWatcher 的 finished信号,由于给watcher设置future,当监控到future执行结束后,可以获取它的执行结果,调用的是result()函数: 

    1. connect(fw, &QFutureWatcher<int>::finished, [&]{
    2. qDebug() << "QFutureWatcher finished";
    3. qDebug() << "result = " << fw->result();
    4. //qDebug() << "num1 = " << num1;
    5. //qDebug() << "num2 = " << num2;
    6. });
    2.5、循环处理事件

    通过循环处理事件来保持界面的响应性,直到 QFuture 执行完成。

    1. //没完成的时候循环处理事件来保持界面的响应性
    2. while (!ft.isFinished())
    3. {
    4. QApplication::processEvents(QEventLoop::AllEvents, 30);
    5. }

    QApplication::processEvents

    函数用于处理事件循环中的事件,确保界面的响应性。调用该函数会处理当前事件队列中的所有事件,直到事件队列为空或者达到指定的最大处理时间。 

    QEventLoop::AllEvents

    参数表示处理所有类型的事件,包括用户输入事件、定时器事件、绘图事件等。

    30 参数表示最大处理时间为30毫秒,即函数最多处理30毫秒的事件后返回。这样可以避免在处理事件的过程中阻塞主线程过长时间,确保界面的及时响应。

    3、最终代码

    1. #include "ch74.h"
    2. #include <QDebug>
    3. #include <QtConcurrent>
    4. #include <QFuture>
    5. #include <QFutureWatcher>
    6. ch74::ch74(QWidget *parent)
    7. : QWidget(parent)
    8. {
    9. ui.setupUi(this);
    10. }
    11. ch74::~ch74()
    12. {}
    13. int ch74::timeTask(int& num1, int& num2)
    14. {
    15. for (int i = 0; i < 1000; i++)
    16. {
    17. num1++;
    18. num2++;
    19. qDebug() << num1;
    20. qDebug() << num2;
    21. }
    22. return num1 + num2;
    23. }
    24. void ch74::on_pushButton_clicked()
    25. {
    26. int num01 = 0;
    27. int num02 = 0;
    28. //创建 QFutureWatcher 对象,用于监视一个 QFuture 对象的执行状态
    29. QFutureWatcher<int>* fw = new QFutureWatcher<int>;
    30. //通过 QtConcurrent::run 函数在一个新线程中执行 ch74 类的成员函数 timeTask.(并发)
    31. // num01 和 num02 作为参数传递给 timeTask 函数。
    32. QFuture<int> ft = QtConcurrent::run(this, &ch74::timeTask, num01, num02);
    33. //通过 fw->setFuture(ft) 将 QFuture<int> 对象与 QFutureWatcher 相关联,
    34. //这样 QFutureWatcher 就能监视 QFuture 对象的执行状态
    35. fw->setFuture(ft);
    36. //连接 QFutureWatcher 的 finished 信号,当 QFuture 执行完成时输出调试信息,注意这里由于捕获的是指针fw
    37. //所以lambda表达式里用的是[&]而不是[=]
    38. connect(fw, &QFutureWatcher<int>::finished, [&] {
    39. qDebug() << "QFutureWatcher finished";
    40. qDebug() << "result = " << fw->result();
    41. //qDebug() << "num1 = " << num1;
    42. //qDebug() << "num2 = " << num2;
    43. });
    44. //没完成的时候循环处理事件来保持界面的响应性
    45. while (!ft.isFinished())
    46. {
    47. //QApplication::processEvents 函数用于处理事件循环中的事件,确保界面的响应性
    48. //调用该函数会处理当前事件队列中的所有事件,直到事件队列为空或者达到指定的最大处理时间
    49. QApplication::processEvents(QEventLoop::AllEvents, 30);
    50. }
    51. }

    以上就是QtConcurrent返回值与run方法的参数说明的简单介绍

    都看到这里了,点个赞再走呗朋友~

    加油吧,预祝大家变得更强!

  • 相关阅读:
    10 个最佳地理空间数据分析 GIS 软件
    用C语言将无符号整数转换为字符串
    虚拟DOM的发展趋势和潜在创新
    STM8应用笔记2.变量空间的分配
    静态ip和动态ip区别在哪?
    一百七十二、Flume——Flume采集Kafka数据写入HDFS中(亲测有效、附截图)
    矩阵账号搭建流程,3步学会,直接拿去用即可
    Kali生成windows木马程序
    flink去重(一)flink、flink-sql中常见的去重方案总结
    【学习笔记】深度学习分布式系统
  • 原文地址:https://blog.csdn.net/LF__plus/article/details/138200087