1. 使用 QtConcurrent (最简单的方式)
cpp
// 按钮点击槽函数
void MainWindow::on_pushButton_clicked()
{
// 禁用按钮防止重复点击
ui->pushButton->setEnabled(false);
// 使用QtConcurrent在后台线程执行耗时任务
QFuture<void> future = QtConcurrent::run([this]() {
// 这里是耗时业务代码
doTimeConsumingTask();
// 任务完成后在UI线程恢复按钮状态
QMetaObject::invokeMethod(this, [this]() {
ui->pushButton->setEnabled(true);
QMessageBox::information(this, "完成", "耗时任务执行完毕");
}, Qt::QueuedConnection);
});
}
2. 使用 QThread + moveToThread (更灵活的方式)
cpp
// 工作类声明
class Worker : public QObject {
Q_OBJECT
public slots:
void doWork() {
// 耗时业务处理
for(int i = 0; i < 100; i++) {
QThread::msleep(50);
emit progress(i);
}
emit finished();
}
signals:
void progress(int value);
void finished();
};
// 在窗口类中使用
void MainWindow::on_pushButton_clicked()
{
ui->pushButton->setEnabled(false);
QThread* thread = new QThread;
Worker* worker = new Worker;
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::finished, thread, &QThread::quit);
connect(worker, &Worker::finished, worker, &QObject::deleteLater);
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(worker, &Worker::progress, this, [this](int value) {
ui->progressBar->setValue(value);
});
connect(thread, &QThread::finished, this, [this]() {
ui->pushButton->setEnabled(true);
});
thread->start();
}
最佳实践建议
简单任务:优先使用
QtConcurrent::run()
,代码最简洁复杂任务:使用
QThread
+moveToThread
,灵活性最高
注意事项
非UI线程中不能直接操作界面组件
跨线程通信使用信号槽或
QMetaObject::invokeMethod
记得管理好线程和对象生命周期,避免内存泄漏
提供取消机制,特别是长时间运行的任务
显示进度反馈,提升用户体验
以上方法都能有效避免UI冻结,保持界面响应流畅。