QT异步编程之QtConcurrent

打印 上一主题 下一主题

主题 864|帖子 864|积分 2592

一、概述

1、QtConcurrent模块提供了一组便捷的函数,用于在不显示创建和管理线程的情况下实现并发编程。
2、它通过将使命提交给线程池来执行,从而制止了频繁创建和烧毁线程带来的性能开销。
3、QtConcurrent非常得当处置惩罚需要并行执行的批量使命,并且能够主动管理线程和使命的分配。
二、QtConcurrent的核心功能 

1、并行盘算:支持对容器(如QList、QVector)中的元素举行并行处置惩罚。

(1)QtConcurrent::map()

   对容器中的每个元素应用一个函数(原地修改)
  1. QList list = {1, 2, 3, 4, 5};
  2. for (auto value : list)
  3.      qDebug() << &list << value;
  4. auto future = QtConcurrent::map(list, [](int &value) { value *= 2;});
  5. future.waitForFinished();
  6. for (auto value : list)
  7.      qDebug() << &list << value;
  8. //结果
  9. 0xf5949ff688 1
  10. 0xf5949ff688 2
  11. 0xf5949ff688 3
  12. 0xf5949ff688 4
  13. 0xf5949ff688 5
  14. 0xf5949ff688 2
  15. 0xf5949ff688 4
  16. 0xf5949ff688 6
  17. 0xf5949ff688 8
  18. 0xf5949ff688 10
复制代码
(2)QtConcurrent::mapped()

   对容器中的每个元素应用一个函数,并返回一个新的容器 
  1. int convert(int value)
  2. {
  3.     return value * 2;
  4. }
  5. QList<int> list = {1, 2, 3, 4, 5};
  6. for (auto value : list)
  7.     qDebug() << &list << value;
  8. auto future = QtConcurrent::mapped(list, convert);
  9. future.waitForFinished();
  10. QList<int> result = future.results();
  11. for (auto value : result)
  12.     qDebug() <<  &result << value;
  13. //结果
  14. 0xda6f18fbe0 1
  15. 0xda6f18fbe0 2
  16. 0xda6f18fbe0 3
  17. 0xda6f18fbe0 4
  18. 0xda6f18fbe0 5
  19. 0xda6f18fc08 2
  20. 0xda6f18fc08 4
  21. 0xda6f18fc08 6
  22. 0xda6f18fc08 8
  23. 0xda6f18fc08 10
复制代码
(3)Qt::Concurrent::filter()

   过滤容器中的元素(原地修改)
  1. QList<int> list = {1, 2, 3, 4, 5};
  2. for (auto value : list)
  3.     qDebug() << &list << value;
  4. auto future = QtConcurrent::filter(list, [](int value) { return value % 2 == 0;});
  5. future.waitForFinished();
  6. for (auto value : list)
  7.      qDebug() << &list << value;
  8. //运行结果
  9. 0xd8871f9c8 1
  10. 0xd8871f9c8 2
  11. 0xd8871f9c8 3
  12. 0xd8871f9c8 4
  13. 0xd8871f9c8 5
  14. 0xd8871f9c8 2
  15. 0xd8871f9c8 4
复制代码
2、使命分发:支持将函数或方法分发到线程池中执行

(1)QtConcurrent::run()

   将函数分发到线程池中执行,不会阻塞当前线程;
  返回一个QFuture对象,用于获取使命的执行效果或监视使命状态
  支持普通函数、Lambda表达式、成员函数等多种调用方式
  1. int add(int a, int b)
  2. {
  3.     qDebug() << "Task running in thread" << QThread::currentThreadId();
  4.     return a + b;
  5. }
  6. void print()
  7. {
  8.     QThread::sleep(2);
  9.     qDebug() << "Task print in thread" << QThread::currentThreadId();
  10. }
  11. class MyClass
  12. {
  13. public:
  14.     void function()
  15.     {
  16.         qDebug() << "Task function in thread" << QThread::currentThreadId();
  17.     }
  18. };
  19. int main(int argc, char *argv[])
  20. {
  21.     QApplication a(argc, argv);
  22.     qDebug() << "start";
  23.     //无参调用
  24.     QtConcurrent::run(print);
  25.     //有参调用
  26.     QtConcurrent::run(add, 3, 4);
  27.     //Lambda表达式
  28.     QtConcurrent::run([](int a, int b){
  29.         qDebug() << "Task Lambda in thread" << QThread::currentThreadId();
  30.         return a + b;
  31.     }, 2, 3);
  32.     //成员函数
  33.     MyClass test;
  34.     QtConcurrent::run(&test, &MyClass::function);
  35.    
  36.     qDebug() << "end";
  37.     return a.exec();
  38. }
  39. //结果
  40. start
  41. end
  42. Task function in thread 0x6c38
  43. Task running in thread 0x8fd0
  44. Task print in thread 0x4a28
复制代码
3、异步编程:支持异步执行使命,并通过信号与槽机制通知使命完成

(1)QFuture:QFuture的效果查询函数,都是阻塞型的,会等待QtConcurrent::run()竣事

   表示异步盘算的效果,可以通过result()或results()获取盘算效果,支持等待使命完成(waitForFinished());
  1. int getCount(int n)
  2. {
  3.     int i = 0;
  4.     while (i < n)
  5.     {
  6.         qDebug() << i;
  7.         QThread::sleep(1);
  8.         ++i;
  9.     }
  10. }
  11. int main(int argc, char *argv[])
  12. {
  13.     QApplication a(argc, argv);
  14.     qDebug() << "start";
  15.     QFuture<int> future = QtConcurrent::run(getCount, 4);
  16.     qDebug() << future.result() << future.resultCount();  //会阻塞线程
  17.     qDebug() << "end";
  18.     return a.exec();
  19. }
  20. //结果
  21. start
  22. 0
  23. 1
  24. 2
  25. 3
  26. -1 1
  27. end
复制代码
(2)QFutureWatcher:用于监视QFuture的状态,通过信号与槽机制通知使命完成、进度更新等 

   QFuture类本身未继承QObject,以是没法直接使用信号槽,以是需要另一个监视类QFutureWatcher。
  1. int getCount(int n)
  2. {
  3.     int i = 0;
  4.     while (i < n)
  5.     {
  6.         qDebug() << i;
  7.         QThread::sleep(1);
  8.         ++i;
  9.     }
  10.     return -1;
  11. }
  12. int main(int argc, char *argv[])
  13. {
  14.     QApplication a(argc, argv);
  15.     qDebug() << "start";
  16.     QFuture<int> future = QtConcurrent::run(getCount, 4);
  17.     QFutureWatcher<int> watcher;
  18.     watcher.setFuture(future);
  19.     QObject::connect(&watcher, &QFutureWatcher<int>::finished, [&](){
  20.         qDebug() << QThread::currentThreadId() << future.result() << future.resultCount();
  21.     });
  22.     qDebug() << "end";
  23.     return a.exec();
  24. }
  25. //结果
  26. start
  27. 0
  28. QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race
  29. end
  30. 1
  31. 2
  32. 3
  33. 0x8818 -1 1
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表