4. QtConcurrent::run异步执行
任务目标
本案例演示如何使用 QtConcurrent::run 将耗时函数放到后台线程执行,并通过 QFutureWatcher 在函数完成时自动获取返回值,避免阻塞主线程(UI线程)。
环境依赖
在项目文件(.pro)中添加:
QT += concurrent widgets
关键完整代码
#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>
#include <QtConcurrent>
#include <QFutureWatcher>
#include <QThread>
// 后台执行的耗时函数(模拟计算)
int heavyWork(int input) {
QThread::sleep(2); // 模拟耗时2秒
return input * 10;
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QLabel statusLabel("点击按钮开始异步计算");
QPushButton startBtn("开始计算");
layout.addWidget(&statusLabel);
layout.addWidget(&startBtn);
// QFutureWatcher 用于监听异步任务结果
QFutureWatcher<int> watcher;
// 任务完成时更新UI
QObject::connect(&watcher, &QFutureWatcher<int>::finished, [&]() {
statusLabel.setText(QString("计算完成,结果: %1").arg(watcher.result()));
startBtn.setEnabled(true);
});
QObject::connect(&startBtn, &QPushButton::clicked, [&]() {
statusLabel.setText("正在后台计算...");
startBtn.setEnabled(false);
// 在后台线程运行 heavyWork(5)
QFuture<int> future = QtConcurrent::run(heavyWork, 5);
watcher.setFuture(future); // 关联future以监听完成
});
window.show();
return app.exec();
}
运行与验证
运行方式:直接编译运行上述代码。点击“开始计算”按钮后,界面标签立即变为“正在后台计算...”,此时窗口仍可正常拖动、响应(主线程未被阻塞)。约2秒后标签自动更新为“计算完成,结果: 50”。
验证要点:
- 点击按钮后,若窗口在计算期间仍能正常移动或响应其他操作,说明
heavyWork确实在后台线程执行,主线程未被阻塞。 - 最终标签显示结果 50(即 5×10),证明
QFutureWatcher成功获取了后台线程的返回值。 - 计算期间按钮处于禁用状态,完成后恢复可用,说明
finished信号被正确触发。
判定标准:若界面在2秒等待期间无卡顿,且最终显示“结果: 50”,则案例实现正确。