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

【Qt】QtConcurrent

目录

    • 概述
    • 成员函数
      • `run`
        • 原型
        • 解释
        • 细节
        • 使用
        • Qt Help的例子
    • example
    • 参考文章

概述

  1. QtConcurrent用于多任务并发的高级API,无需显式管理线程的创建和同步
  2. QtConcurrent没有事件循环
  3. QtConcurrent没有任务优先级
  4. 相比于QThreadQtConcurrent更方便
  5. Cmake添加QtConcurrent模块

成员函数

run

原型
template <typename T>
QFuture<T> QtConcurrent::run(Function function, ...)

Equivalent to

QtConcurrent::run(QThreadPool::globalInstance(), function, ...);
解释

Runs function in a separate thread. The thread is taken from the global QThreadPool. Note that function may not run immediately; function will only be run once a thread becomes available.

T is the same type as the return value of function. Non-void return values can be accessed via the QFuture::result() function.

Note: The QFuture returned can only be used to query for the running/finished status and the return value of the function. In particular, canceling or pausing can be issued only if the computations behind the future has not been started.

在单独的线程运行,这个线程取自global QThreadPool,该函数可能不会立即运行,只有在线程可用时才会执行
T 与函数返回值相同
返回的QFuture对象只能用于查询函数的运行 / 完成状态以及返回值。尤其要注意的是,只有在QFuture背后对应的计算尚未开始时,才能发出取消或暂停操作(通过QtConcurrent::run()返回的QFuture不支持取消、暂停)

细节

使用QtConcurrent::run()来运行自定义类的成员函数时一定要确保自定义类继承了QObject,不然线程池的初始化会有问题
默认第一个参数传递的this

why
QtConcurrent::run的第一个参数使用了QThreadPool,而QThreadPool是由QObject派生而来
有待考究

使用

QtConcurrent::run() also accepts pointers to member functions. The first argument must be either a const reference or a pointer to an instance of the class. Passing by const reference is useful when calling const member functions; passing by pointer is useful for calling non-const member functions that modify the instance

QtConcurrent::run()函数也接受指向成员函数的指针。第一个参数必须是const 引用或类实例的指针

Qt Help的例子

For example, calling QByteArray::split() (a const member function) in a separate thread is done like this:

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

Calling a non-const member function is done like this:

 // 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

Calling a lambda function is done like this:

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

example

  1. QtConcurrent
class Threadtest : public QMainWindow
{
    Q_OBJECT

public:
    Threadtest(QWidget *parent = Q_NULLPTR);  
private:
    Ui::ThreadtestClass ui;
    void work();//成员函数
};
Threadtest::Threadtest(QWidget* parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    connect(ui.btn_start, &QPushButton::clicked, [=]()
        {  
        //将成员函数放入参数中(成员函数需要引用指针)
            QtConcurrent::run(this, &Threadtest::work);
        });
}
void Threadtest::work()
{
    qDebug() << "子线程运行:" << QThread::currentThreadId();
    QThread::sleep(5);
    qDebug() << "子线程结束:" << QThread::currentThreadId();
}
// A time-consuming function
int heavyTask(int value)
{
    QThread::sleep(1); // Simulate a long computation
    qDebug() << "thread id=" << QThread::currentThreadId();
    return value * value;
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    // List of integers to process
    QList<int> values = {1, 2, 3, 4, 5};

    // Use QtConcurrent to run the heavyTask function on each value in the list
    QFuture<int> future = QtConcurrent::mapped(values, heavyTask);

    // Create a QFutureWatcher to monitor the progress of the future
    QFutureWatcher<int> watcher;

    // Connect signals to monitor the progress
    QObject::connect(&watcher, &QFutureWatcher<int>::started, []()
                     { qDebug() << "Task started"; });

    QObject::connect(&watcher, &QFutureWatcher<int>::finished, [&future]()
                     {
        qDebug() << "Task finished";

        // Retrieve and display the results
        QList<int> results = future.results();
        for (int result : results) {
            qDebug() << "Result:" << result;
        } });

    QObject::connect(&watcher, &QFutureWatcher<int>::progressValueChanged, [](int progress)
                     { qDebug() << "Progress:" << progress; });

    // Set the future to the watcher
    watcher.setFuture(future);

    return app.exec();
}

// 输出
Task started
Progress: 0
thread id= 0x3954
thread id= 0x3f7c
thread id= 0x233c
thread id= 0x568
thread id= 0x4768
Progress: 1
Progress: 5
Task finished
Result: 1
Result: 4
Result: 9
Result: 16
Result: 25
  1. QThreadPool
#include <QCoreApplication>
#include <QThreadPool>
#include <QRunnable>
#include <QDebug>
#include <QThread>

// 一个自定义的 QRunnable 任务
class HeavyTask : public QRunnable {
public:
    HeavyTask(int value) : m_value(value) {}

    void run() override {
        QThread::sleep(1); // 模拟长时间计算
        int result = m_value * m_value;
        qDebug() << "结果:" << result;
    }

private:
    int m_value;
};

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QThreadPool *threadPool = QThreadPool::globalInstance();

    QList<int> values = {1, 2, 3, 4, 5};
    for (int value : values) {
        HeavyTask *task = new HeavyTask(value);
        threadPool->start(task);
    }

    threadPool->waitForDone(); // 等待所有任务完成

    return app.exec();
}

参考文章

QT从入门到入土(五(2))——多线程(QtConcurrent::run())和线程池 - 唯有自己强大 - 博客园
QtConcurrent和QFuture的使用-CSDN博客
Qt并发模块Qt Concurrent的使用_qtconcurrent 用法-CSDN博客
Qt多线程:QtConcurrent + QFuture + QFutureWatcher_51CTO博客_Qt多线程通信
[最详细的Qt多线程的三种方法之三QtConcurrent::run()+QThreadPool_qtconcurrent::run(qthreadpool::globalinstance(), -CSDN博客


http://www.kler.cn/a/472315.html

相关文章:

  • 你好,2025!JumpServer开启新十年
  • 【网络安全 | 漏洞挖掘】通过监控调试模式实现价值$15k的RCE
  • uniapp实现后端数据i18n国际化
  • Mysql--基础篇--事务(ACID特征及实现原理,事务管理模式,隔离级别,并发问题,锁机制,行级锁,表级锁,意向锁,共享锁,排他锁,死锁,MVCC)
  • 用OpenCV实现UVC视频分屏
  • oracle闪回恢复数据:(闪回查询,闪回表,闪回库,回收站恢复)
  • 【UE5 C++课程系列笔记】21——弱指针的简单使用
  • 回归预测 | MATLAB实ELM-Adaboost多输入单输出回归预测
  • Mono里运行C#脚本23—mono_jit_exec
  • Python 批量生成Word 合同
  • xss-labs(level11-20)【通关技巧】
  • el-table 使用el-form 表单验证
  • STM32学习(十)
  • 嵌入式入门Day38
  • Android Process 问题:NoSuchMethodError,No static method myProcessName()
  • HTML5实现好看的博客网站、通用大作业网页模板源码
  • 第19章 数据库备份与恢复
  • 基于单片机的观赏类水草养殖智能控制系统的设计(论文+源码)
  • 采用标准化的方式开展设计-研发中运用设计模式
  • 中国科技统计年鉴EXCEL版(2021-2023年)-社科数据
  • SAP 01-初识AMDP(ABAP-Managed Database Procedure)
  • 一种用于无人机任务卸载的轻量级深度强化学习框架
  • Android系统默认开启adb root模式
  • npm发布自定义包
  • Cannot run program “docker“: CreateProcess error=2,系统找不到指定的文件
  • 深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现