概述

Concurrent是并发的意思,QtConcurrent是一个命名空间,提供了一些高级的 API,使得在编写多线程的时候,无需使用低级线程原语,如读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器内核数自动调整使用的线程数。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展。

而这里要讲的是QtConcurrent::run函数的用法。
函数原型如下:

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

简单的说,QtConcurrent::run()函数会在一个单独的线程中执行,并且该线程取自全局QThreadPool,该函数的返回值通过QFuture API提供。
请注意:该函数可能不会立即运行; 函数只有在线程可用时才会运行。
通过QtConcurrent::run()返回的QFuture不支持取消、暂停,返回的QFuture只能用于查询函数的运行/完成状态和返回值。

导入模块

在 C++ API changes 有关于 Qt Concurrent 的更改说明

Qt Concurrent has been moved from Qt Core to its own module

大致意思就是,Qt Concurrent已经从 QtCore 中移除并成为了一个独立的模块。
所以在使用的时候需要在工程文件中导入模块,如下

QT += concurrent

示例

通过一个简单的例子来看一下效果

#include "widget.h"
#include <QDebug>
#include <QThread>
#include <QtConcurrent>
#include <QFuture>Widget::Widget(QWidget *parent): QWidget(parent)
{m_pBtn = new QPushButton("Click me",this);m_pBtn->setGeometry(100,100,220,70);connect(m_pBtn,&QPushButton::clicked,this,&Widget::onBtnClicked);
}void func(QString str)
{qDebug() << __FUNCTION__ << str << QThread::currentThreadId() << QThread::currentThread();
}void Widget::onBtnClicked()
{
#if 0QFuture<void> f1 =QtConcurrent::run(func,QString("aa"));f1.waitForFinished();
#elseQFuture < void > future =  QtConcurrent::run([=](){qDebug() << __FUNCTION__  << QThread::currentThreadId() << QThread::currentThread();});QFuture < void > future2 = QtConcurrent::run([=](){qDebug() << __FUNCTION__  << QThread::currentThreadId() << QThread::currentThread();});
#endif
}

做了一个简单的界面,通过点击按钮来调用 QtConCurrent::run函数。

这里在按钮的槽函数中用了两种方法来调用,一种是调用外部 extern 函数,一种是使用了Lambda函数,两种方式只是写法上的不同,结果都是一样的。

注意:第一种方法调用外部函数,如果该函数是类的成员函数,会报以下错误 : reference to no-static member function must be called…
如下图:

定义外部函数

extern void func(QString str);

这里运行了第二种方法,Lambda函数来实现。
点击按钮后输出以下结果:

operator() 0x700005df0000 QThread(0x7fe63ccf8420, name = "Thread (pooled)")
operator() 0x700005e73000 QThread(0x7fe63cc56630, name = "Thread (pooled)")

连续调用两次,分别在不同的线程中执行的,这也就验证了该函数的作用。

问题来了

看到这儿,一定会有个疑问,上面说调用的函数必须是外部函数,通过 extern 来定义函数,那么,如果要调用类的成员函数怎么办呢?先来看看 Qt 文档的介绍。

使用成员函数

QtConcurrent :: run()也接受指向成员函数的指针。第一个参数必须是一个const引用或一个指向该类实例的指针。const成员函数一般传递 常量引用 (const reference),而非常量成员函数一般传递 指针 (pointer)

例如,在一个单独的线程中调用QByteArray :: split()(一个const成员函数)就像这样完成:

// call 'QList<QByteArray>  QByteArray::split(char sep) const' in a separate thread
QByteArray bytearray = "hello world";
QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
...
QList<QByteArray> result = future.result();

调用非const成员函数是这样完成的:

// call 'void QImage::invertPixels(InvertMode mode)' in a separate thread
QImage image = ...;
QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba);
...
future.waitForFinished();
// At this point, the pixels in 'image' have been inverted

OK,大概清楚了,我们修改一下上面的示例,让 QtConCurrent::run去调用成员函数。
看代码:

#include "widget.h"
#include <QDebug>
#include <QThread>
#include <QtConcurrent>
#include <QFuture>Widget::Widget(QWidget *parent): QWidget(parent)
{m_pBtn = new QPushButton("Click me",this);m_pBtn->setGeometry(100,100,220,70);connect(m_pBtn,&QPushButton::clicked,this,&Widget::onBtnClicked);
}void Widget::onBtnClicked()
{
#if 1//调用外部函数QFuture<void> f1 =QtConcurrent::run(func,QString(index++));//调用类成员函数QFuture<void> f2 =QtConcurrent::run(this,&Widget::myFunc,QString("aaa"));
#else  //使用Lambda函数实现QFuture < void > future =  QtConcurrent::run([=](){qDebug() << __FUNCTION__  << QThread::currentThreadId() << QThread::currentThread();});QFuture < void > future2 = QtConcurrent::run([=](){qDebug() << __FUNCTION__  << QThread::currentThreadId() << QThread::currentThread();});
#endif
}void Widget::myFunc(const QString & str)
{qDebug() << __FUNCTION__ << str << QThread::currentThreadId() << QThread::currentThread();
}void func(QString str)
{qDebug() << __FUNCTION__ << str << QThread::currentThreadId() << QThread::currentThread();
}

简单说明一下,这里新增了一个成员函数myFunc,在槽函数onBtnClicked中进行调用。

//调用类成员函数QFuture<void> f2 =QtConcurrent::run(this,&Widget::myFunc,QString("aaa"));

使用Lambda函数

调用lambda函数是这样完成的:

QFuture<void> future = QtConcurrent::run([=]() {// Code in this block will run in another thread
});
...

上面示例中已经添加了Lambda 函数的调用方法,如果说将要调用的函数执行的内容不多的话 可以考虑使用Lambda 函数,使用会比较简单。

参考资料:http://doc.qt.io/qt-5/qtconcurrentrun.html

Qt QtConcurrent之 Run 函数用法相关推荐

  1. QT多线程run函数不能使用信号与槽

    一.问题描述 今天遇到一个问题,我在一个子线程中定义一个信号与槽函数,然后直接连接,最后会报错Socket notifiers cannot be enabled or disabled from a ...

  2. setEvent Qt多线程步骤 基于Qthraed 重写Run函数

    1.创建类基于Qthread,重写run函数 头文件里 class Thread : public QThread{public:P* m_p;bool m_is;bool m_b;Thread(){ ...

  3. Qt 并行计算 Concurrent Run的翻译

    资料来源:https://doc.qt.io/qt-5/qtconcurrentrun.html Concurrent Run的简介: QtConcurrent::run() 是开启单独一个线程来运行 ...

  4. Qt QtConcurrent多线程 - map、mapped和mappedReduced

    Qt中的 Concurrent 模块为我们提供了在一个序列容器类型针对每一个元素的多线程并行运算,比如 QList . QVector . QtConcurrent::map() :对序列的每一项元素 ...

  5. python回调函数实例详解_Python回调函数用法实例详解

    本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函 ...

  6. fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)

    1.fork()创建子进程详细步骤 2.fork()系统调用函数用法 一个现有进程可以调用fork函数创建一个新的进程. #include<unistd.h> pid_t fork(voi ...

  7. QT中Model-View-Delegate委托代理机制用法介绍

    文章目录 本地数据加载(Data) 添加数据模型(Model) 添加代理模型(Proxy) 添加元素的代理(Delegate) 添加视图层(View) 使用效果 之前的一篇文章中介绍过QT的委托代理机 ...

  8. pyspark及Spark报错问题汇总及某些函数用法。

    此贴,主要记录本人在工作中遇到的某些报错问题,并提出自己的解决办法. 1. spark = SparkSession.builder()  TypeError: 'Builder' object is ...

  9. c语言strcmp函数用法_strcmp()C库函数用法和示例

    c语言strcmp函数用法 C programming standard library provides strcmp() function in order to compare two stri ...

最新文章

  1. 第二节 RabbitMQ配置
  2. 区块链BaaS云服务(36)欧盟EBSI“使用场景”
  3. 千亿化妆品市场规模背后,女人正在失去不化妆的权利
  4. img文件编辑_只会用chmod 777?Linux下的文件权限居然还有这么多骚操作
  5. Rocketmq vs Kafka
  6. Java基础面试题:AQS组件总结
  7. 浅谈批处理for命令中的变量扩展
  8. Java-好玩的猜数小游戏
  9. 2016团体程序设计天梯赛-决赛-部分题解
  10. Kong 网关 | Rate Limiting 限流
  11. Open API: 电信ECP能力开放平台
  12. win8运行matlab7.0,Win8.1系统中matlab7.0不兼容的解决方法
  13. 计算机网络实验三——IP网络规划与路由设计
  14. 把Excel批注的“红三角”放在单元格左上角_44个Excel使用技巧:怪不得同事表格类工作那么快完成,学以致用...
  15. 博主文章导航(分门别类,实时更新,永久置顶)
  16. 用AI写代码 -- Github Copilot测试
  17. 非极大值抑制算法(Non-Maximum Suppression,NMS)
  18. mac os 系统升级到 Catalina 版本后出现应用打不开 ,闪退,意外退出问题
  19. 【不务正业系列】爬虫易烊千玺QQ音乐扑通社区“阅读”、“动态”和“成员”数据
  20. HyperLPR3车牌识别-五分钟搞定: 中文车牌识别光速部署与使用

热门文章

  1. 《网易智企技术合辑》正式发布
  2. LeetCode_559.N叉树的最大深度
  3. jenkins+gitlab构建自动化集成
  4. 苏宁大促高并发要求下的售后服务运营能力承诺服务系统架构实战\n
  5. Mac下Git安装及配置
  6. 安卓MP3播放器开发实例(3)之进度条和歌词更新的实现
  7. linux下find查找带有指定权限的文件(windows下编译的源代码文件)
  8. 編程之美資格賽傳話遊戲
  9. 结束SQL阻塞的进程
  10. 【网址收藏】Porter:面向裸金属环境的 Kubernetes 开源负载均衡器