当前位置: 首页 > article >正文

QT异步编程之QtConcurrent

一、概述

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.kler.cn/a/567420.html

相关文章:

  • C语言(17)------------>数组的练习
  • 【练习】【贪心】力扣134. 加油站
  • 人工智能销售客服app开发,OpenAI宣布GPT-5免费使用?Deepseek让AI巨头全跪了
  • 【 实战案例篇三】【某金融信息系统项目管理案例分析】
  • leetcode28 找出字符串第一个匹配值的下标 KMP算法
  • Python 的守护线程
  • 奇异值分解(SVD)的原理与应用
  • 每日一题之屏蔽信号
  • Nginx 配置与常用命令速查手册
  • 计算机视觉|ViT详解:打破视觉与语言界限
  • 【弹性计算】弹性裸金属服务器和神龙虚拟化(一):功能特点
  • PHP缓存技术优化:提升网站性能的关键
  • c++ std::forward_list使用笔记
  • 利用three.js在Vue项目中展示重构的stl模型文件
  • Java进阶——注解一文全懂
  • AIP-156 单例资源
  • 一周一个Unity小游戏2D反弹球游戏 - 球的死区及球重生
  • React + TypeScript 实现 SQL 脚本生成全栈实践
  • 3D打印涡轮叶片-当传统铸造遇上“不可能任务”
  • Pytest之fixture的常见用法