qt-C++笔记之使用QtConcurrent异步地执行槽函数中的内容,使其不阻塞主界面

qt-C++笔记之使用QtConcurrent异步地执行槽函数中的内容,使其不阻塞主界面

code review!

文章目录

1.QtConcurrent::run基本用法

QtConcurrent::run 是 Qt 框架中一个非常有用的函数,用于在不同的线程中异步执行函数或者成员函数,这样可以避免阻塞主线程,提高应用程序的响应性。这个函数是 Qt 并发编程模块的一部分,使用前需要包含头文件 <QtConcurrent>

基本用法

QtConcurrent::run 可以启动任何可调用的对象,包括普通函数、类成员函数以及 lambda 表达式。它返回一个 QFuture<T> 对象,你可以使用这个对象来查询任务的状态或结果。

启动一个全局函数或静态成员函数
cpp 复制代码
#include <QtConcurrent>

void myFunction(int arg1, double arg2) {
    // 处理函数
}

int main() {
    QFuture<void> future = QtConcurrent::run(myFunction, 1, 2.0);
}
使用 Lambda 表达式
cpp 复制代码
#include <QtConcurrent>

int main() {
    auto lambda = [] (int value) {
        // 一些处理
    };
    QFuture<void> future = QtConcurrent::run(lambda, 42);
}
启动类的成员函数
cpp 复制代码
#include <QtConcurrent>

class MyClass {
public:
    void myMemberFunction(int arg) {
        // 处理函数
    }
};

int main() {
    MyClass myObject;
    QFuture<void> future = QtConcurrent::run(&MyClass::myMemberFunction, &myObject, 123);
}

指定执行的线程

默认情况下,QtConcurrent::run 使用全局线程池来执行任务。但是,你也可以指定一个自定义的 QThreadPool 来运行任务。

cpp 复制代码
#include <QtConcurrent>

void myFunction() {
    // 函数实现
}

int main() {
    QThreadPool pool;
    pool.setMaxThreadCount(2);  // 设置线程池大小

    QFuture<void> future = QtConcurrent::run(&pool, myFunction);
    future.waitForFinished();  // 等待任务完成
}

使用返回值

如果被调用的函数有返回值,你可以通过 QFuture<T> 来获取这个值。

cpp 复制代码
#include <QtConcurrent>

int computeValue() {
    return 42;
}

int main() {
    QFuture<int> future = QtConcurrent::run(computeValue);
    int result = future.result();  // 获取结果
    return result;
}

注意事项

  1. 线程安全 :确保你传递给 QtConcurrent::run 的函数是线程安全的,特别是当你在多个线程中访问共享数据时。
  2. 资源管理:当你在多线程环境中工作时,需要特别注意资源管理和数据同步。
  3. 生命周期管理 :确保所有 QtConcurrent::run 使用的对象在任务执行期间保持有效。

2.代码1:槽函数定义------>QtConcurrent::run(Lambda表达式)------>全局函数

运行

cpp 复制代码
#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QtConcurrent>

// 假设这是一个耗时的函数
void heavyFunction() {
    // 模拟耗时操作,例如计算或数据处理
    for (int i = 0; i < 100000000; i++) {
        double x = i * 0.001;
        x = x / 2.0;
    }
}

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        // 创建按钮
        QPushButton *pushButton = new QPushButton("Run Heavy Function", this);
        pushButton->setGeometry(100, 50, 200, 50);

        // 连接按钮的点击信号到相应的槽
        connect(pushButton, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked);
    }

public slots:
    void on_pushButton_clicked() {
        // 使用 QtConcurrent 运行重耗时函数
        QtConcurrent::run([=] {
            heavyFunction();
        });
    }
};

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

    MainWindow w;
    w.show();

    return app.exec();
}

#include "main.moc"  // 确保包含 moc 文件以处理 QObject 的元信息

3.代码2:槽函数定义------>QtConcurrent::run(Lambda表达式)------>全局函数

运行

cpp 复制代码
#include <QApplication>
#include <QPushButton>
#include <QtConcurrent>

// 假设的耗时函数
void heavyFunction() {
    // 模拟耗时操作,例如进行复杂计算
    for (int i = 0; i < 1000000; ++i) {
        // 模拟计算
    }
}

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

    QPushButton button("Run Heavy Function");
    button.resize(200, 50);
    button.show();

    // 连接按钮的点击信号到一个 lambda 表达式,该表达式异步执行 heavyFunction
    QObject::connect(&button, &QPushButton::clicked, []() {
        QtConcurrent::run([]{
            heavyFunction();
        });
    });

    return app.exec();
}

4.代码3:槽函数定义------>QtConcurrent::run(this,&类名::成员函数)

运行

cpp 复制代码
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QMutex>
#include <QtConcurrent>

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        // 设置主窗口的大小
        this->setFixedSize(400, 300);

        // 创建一个按钮,并设置其显示文本和父窗口
        QPushButton *button = new QPushButton("Run Heavy Function", this);
        button->setGeometry(100, 100, 200, 50);

        // 连接按钮的点击信号到相应的槽函数
        connect(button, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked);
    }

    ~MainWindow() {}

private slots:
    void on_pushButton_clicked() {
        QtConcurrent::run(this, &MainWindow::heavyFunction);
    }

private:
    void heavyFunction() {
        // 锁定互斥锁以安全访问成员变量
        mutex.lock();
        // 操作共享数据
        sharedData++;
        mutex.unlock();

        // 执行其他耗时操作
    }

    int sharedData = 0;  // 一个示例成员变量
    QMutex mutex;        // 互斥锁保护成员变量
};

#include "main.moc"

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

    MainWindow w;
    w.show();

    return app.exec();
}

5.代码4:槽函数定义------>QtConcurrent::run(Lambda表达式[this]{执行内容})

运行

cpp 复制代码
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QMutex>
#include <QtConcurrent>

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        // 设置主窗口的大小
        this->setFixedSize(400, 300);

        // 创建一个按钮,并设置其显示文本和父窗口
        QPushButton *button = new QPushButton("Run Heavy Function", this);
        button->setGeometry(100, 100, 200, 50);

        // 连接按钮的点击信号到相应的槽函数
        connect(button, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked);
    }

    ~MainWindow() {}

private slots:
    void on_pushButton_clicked() {
        // 使用 lambda 表达式在后台线程上运行代码
        QtConcurrent::run([this] {
            // 锁定互斥锁以安全访问成员变量
            mutex.lock();
            // 操作共享数据
            sharedData++;
            mutex.unlock();

            // 执行其他耗时操作
        });
    }
private:
    int sharedData = 0;  // 一个示例成员变量
    QMutex mutex;        // 互斥锁保护成员变量
};

#include "main.moc"

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

    MainWindow w;
    w.show();

    return app.exec();
}

6.上述例程的test.pro

复制代码
TEMPLATE = app
TARGET = qt_test
INCLUDEPATH += .

# Add more modules by appending them here
QT += core gui concurrent

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

SOURCES += main.cpp

HEADERS +=
相关推荐
lingggggaaaa4 小时前
小迪安全v2023学习笔记(一百四十五讲)—— Webshell篇&魔改冰蝎&打乱特征指纹&新增加密协议&过后门查杀&过流量识别
笔记·学习·安全·魔改冰蝎·免杀对抗·免杀技术
虾米Life5 小时前
基于微服务脚手架的视频点播系统 (仿B站) [客户端] -1
c++·qt·微服务·架构
Digitally5 小时前
如何将iPhone上的笔记传输到电脑
笔记·电脑·iphone
落羽的落羽5 小时前
【C++】现代C++的新特性constexpr,及其在C++14、C++17、C++20中的进化
linux·c++·人工智能·学习·机器学习·c++20·c++40周年
CAU界编程小白6 小时前
数据结构系列之十大排序算法
数据结构·c++·算法·排序算法
头发还没掉光光6 小时前
Linux网络初始及网络通信基本原理
linux·运维·开发语言·网络·c++
lkbhua莱克瓦246 小时前
Java基础——常用算法4
java·数据结构·笔记·算法·github·排序算法·快速排序
m0_748248026 小时前
揭开 C++ vector 底层面纱:从三指针模型到手写完整实现
开发语言·c++·算法
海盗猫鸥6 小时前
「C++」string类(2)常用接口
开发语言·c++
序属秋秋秋7 小时前
《Linux系统编程之开发工具》【实战:倒计时 + 进度条】
linux·运维·服务器·c语言·c++·ubuntu·系统编程