qt-C++笔记之使用QtConcurrent异步地执行槽函数中的内容,使其不阻塞主界面
code review!
文章目录
- qt-C++笔记之使用QtConcurrent异步地执行槽函数中的内容,使其不阻塞主界面
- 1.QtConcurrent::run基本用法
- 基本用法
- 启动一个全局函数或静态成员函数
- 使用 Lambda 表达式
- 启动类的成员函数
- 指定执行的线程
- 使用返回值
- 注意事项
- 2.代码1:槽函数定义——>QtConcurrent::run(Lambda表达式)——>全局函数
- 3.代码2:槽函数定义——>QtConcurrent::run(Lambda表达式)——>全局函数
- 4.代码3:槽函数定义——>QtConcurrent::run(this,&类名::成员函数)
- 5.代码4:槽函数定义——>QtConcurrent::run(Lambda表达式[this]{执行内容})
- 6.上述例程的test.pro
1.QtConcurrent::run基本用法
QtConcurrent::run
是 Qt 框架中一个非常有用的函数,用于在不同的线程中异步执行函数或者成员函数,这样可以避免阻塞主线程,提高应用程序的响应性。这个函数是 Qt 并发编程模块的一部分,使用前需要包含头文件 <QtConcurrent>
。
基本用法
QtConcurrent::run
可以启动任何可调用的对象,包括普通函数、类成员函数以及 lambda 表达式。它返回一个 QFuture<T>
对象,你可以使用这个对象来查询任务的状态或结果。
启动一个全局函数或静态成员函数
#include <QtConcurrent>
void myFunction(int arg1, double arg2) {
// 处理函数
}
int main() {
QFuture<void> future = QtConcurrent::run(myFunction, 1, 2.0);
}
使用 Lambda 表达式
#include <QtConcurrent>
int main() {
auto lambda = [] (int value) {
// 一些处理
};
QFuture<void> future = QtConcurrent::run(lambda, 42);
}
启动类的成员函数
#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
来运行任务。
#include <QtConcurrent>
void myFunction() {
// 函数实现
}
int main() {
QThreadPool pool;
pool.setMaxThreadCount(2); // 设置线程池大小
QFuture<void> future = QtConcurrent::run(&pool, myFunction);
future.waitForFinished(); // 等待任务完成
}
使用返回值
如果被调用的函数有返回值,你可以通过 QFuture<T>
来获取这个值。
#include <QtConcurrent>
int computeValue() {
return 42;
}
int main() {
QFuture<int> future = QtConcurrent::run(computeValue);
int result = future.result(); // 获取结果
return result;
}
注意事项
- 线程安全:确保你传递给
QtConcurrent::run
的函数是线程安全的,特别是当你在多个线程中访问共享数据时。 - 资源管理:当你在多线程环境中工作时,需要特别注意资源管理和数据同步。
- 生命周期管理:确保所有
QtConcurrent::run
使用的对象在任务执行期间保持有效。
2.代码1:槽函数定义——>QtConcurrent::run(Lambda表达式)——>全局函数
运行
#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表达式)——>全局函数
运行
#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,&类名::成员函数)
运行
#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]{执行内容})
运行
#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 +=