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

【Qt】多线程学习笔记

Qt多线程学习笔记

一、核心组件

组件/变量作用
QtConcurrent::run快速创建子线程,执行后台任务
QFuture<bool>管理后台任务状态和返回值
QFutureWatcher<bool>监控任务完成状态,触发主线程回调
QAtomicInt m_forceStop线程安全终止标志(替代std::atomic)
QMutex m_progressMutex保护共享进度m_currentProgress,避免竞争
QMetaObject::invokeMethod跨线程更新UI(子线程→主线程)
纯代码UI组件无.ui文件,通过代码创建布局和控件

二、核心使用流程

1. 初始化

  • 纯代码创建UI(进度条、按钮、标签+布局);
  • 绑定QFutureWatcherfinished信号到回调函数;
  • 初始化线程安全变量(m_forceStop=0m_currentProgress=0)。

2. 启动任务

  1. 重置进度和UI状态;
  2. 禁用启动按钮、启用停止按钮;
  3. QtConcurrent::run提交backgroundTask到子线程;
  4. QFutureWatcher绑定QFuture监控任务。

3. 后台任务执行(子线程)

  1. 循环100步模拟耗时计算;
  2. 每步检查m_forceStop(终止标志)和线程中断请求,满足则退出;
  3. QMutexLocker保护m_currentProgress更新(避免竞争);
  4. 调用updateProgress跨线程更新UI;
  5. QThread::msleep(50)控制任务速度。

4. 停止任务

  1. m_forceStop.store(true)设置终止标志;
  2. m_taskFuture.cancel()取消任务,waitForFinished()等待线程退出;
  3. 更新UI状态,恢复按钮可用性;
  4. 断开Watcher连接(冗余但代码保留),解绑Future。

5. 任务完成(主线程回调)

  • 线程安全获取任务返回值;
  • 更新状态标签,弹出完成提示(成功/中断);
  • 恢复按钮状态。

三、关键注意点

  1. 线程安全
    • 共享数据(m_currentProgress)用QMutex保护,读写均需加锁;
    • 终止标志用QAtomicInt(Qt原子类型),避免多线程读写冲突。
  2. 跨线程UI更新
    • 子线程不能直接操作UI,必须通过QMetaObject::invokeMethod+Qt::QueuedConnection切换到主线程。
  3. 资源释放
    • 析构函数调用on_stopBtn_clicked(),确保线程退出后再释放资源;
    • 中文乱码解决:#pragma execution_character_set("utf-8")
  4. 任务终止响应
    • 后台任务内层循环也需检查终止标志,避免长时间阻塞不响应停止指令。

四、代码核心逻辑说明

1. 后台任务核心(backgroundTask

// 核心逻辑:循环计算+终止检查+进度更新
for (int i = 0; i <= 100; ++i) {// 终止检查(线程安全感知停止指令)if (m_forceStop.load() || QThread::currentThread()->isInterruptionRequested()) {return false;}// 模拟耗时计算volatile long long sum = 0;for (long long j = 0; j < 1000000; ++j) {if (m_forceStop.load() || ...) return false; // 内层也检查终止sum += j;}// 线程安全更新进度(加锁)QMutexLocker locker(&m_progressMutex);m_currentProgress = i;// 跨线程更新UIupdateProgress(i);
}

2. 跨线程UI更新(updateProgress

QMetaObject::invokeMethod(this, [this, progress]() {// 主线程执行UI操作(队列连接确保线程安全)ui.progressBar->setValue(progress);ui.statusLabel->setText(QString("状态:运行中...%1%").arg(progress));
}, Qt::QueuedConnection);

3. 停止任务逻辑(on_stopBtn_clicked

m_forceStop.store(true); // 设终止标志
if (m_taskFuture.isRunning()) {m_taskFuture.cancel(); // 取消任务m_taskFuture.waitForFinished(); // 等待线程退出(避免僵尸线程)ui.statusLabel->setText(...) ; // 更新终止状态
}

五.完整Demo

#ifndef QTTHREADMINDEMO_H
#define QTTHREADMINDEMO_H#include <QWidget>
#include <QFuture>
#include <QFutureWatcher>
#include <QMutex>
#include <atomic>
#include <QProgressBar>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QThread>
#include <QtConcurrent> // 添加QtConcurrent头文件
#include <QDebug>
//解决中文乱码
#pragma execution_character_set("utf-8")class QtThreadMinDemo : public QWidget
{Q_OBJECTpublic:QtThreadMinDemo(QWidget *parent = nullptr);~QtThreadMinDemo();private slots:void on_startBtn_clicked();   // 启动任务void on_stopBtn_clicked();    // 停止任务void on_taskFinished();       // 任务完成回调private:// 纯代码创建UIvoid createUI();// 后台任务(子线程执行)bool backgroundTask();// 跨线程更新进度UIvoid updateProgress(int progress);// UI组件(结构体封装,避免成员变量过多)struct UI {QProgressBar *progressBar;QLabel *statusLabel;QPushButton *startBtn;QPushButton *stopBtn;} ui;// 多线程核心变量QFuture<bool> m_taskFuture;         // 管理后台任务QFutureWatcher<bool> m_taskWatcher; // 监控任务状态//std::atomic<bool> m_forceStop;      // 线程安全终止标志QMutex m_progressMutex;             // 保护进度数据的互斥锁int m_currentProgress;              // 共享进度数据QAtomicInt m_forceStop;
};#endif // QTTHREADMINDEMO_H
#include "QtThreadMinDemo.h"QtThreadMinDemo::QtThreadMinDemo(QWidget *parent): QWidget(parent), m_forceStop(false), m_currentProgress(0)
{// 1. 创建UI(纯代码)createUI();// 2. 初始化窗口setWindowTitle("Qt多线程最小Demo(纯代码UI)");setFixedSize(400, 180); // 固定窗口大小// 3. 绑定任务完成信号connect(&m_taskWatcher, &QFutureWatcher<bool>::finished, this, &QtThreadMinDemo::on_taskFinished);
}QtThreadMinDemo::~QtThreadMinDemo()
{// 安全停止任务,释放资源on_stopBtn_clicked();// 断开Watcher连接,避免野指针m_taskWatcher.disconnect();m_taskWatcher.setFuture(QFuture<bool>());
}// 纯代码创建UI组件和布局
void QtThreadMinDemo::createUI()
{// 1. 创建UI组件ui.progressBar = new QProgressBar(this);ui.progressBar->setRange(0, 100);ui.progressBar->setValue(0);ui.statusLabel = new QLabel(this);ui.statusLabel->setText("状态:未启动");ui.startBtn = new QPushButton("启动任务", this);ui.stopBtn = new QPushButton("停止任务", this);ui.stopBtn->setEnabled(false); // 初始禁用停止按钮// 2. 创建布局QVBoxLayout *mainLayout = new QVBoxLayout(this);mainLayout->setSpacing(20);mainLayout->setContentsMargins(30, 20, 30, 20); // 内边距QHBoxLayout *btnLayout = new QHBoxLayout();btnLayout->setSpacing(40);btnLayout->addWidget(ui.startBtn);btnLayout->addWidget(ui.stopBtn);// 3. 组装布局mainLayout->addWidget(ui.progressBar);mainLayout->addWidget(ui.statusLabel);mainLayout->addLayout(btnLayout);// 4. 绑定按钮点击信号connect(ui.startBtn, &QPushButton::clicked, this, &QtThreadMinDemo::on_startBtn_clicked);connect(ui.stopBtn, &QPushButton::clicked, this, &QtThreadMinDemo::on_stopBtn_clicked);
}// 启动任务按钮回调
void QtThreadMinDemo::on_startBtn_clicked()
{// 重置状态m_currentProgress = 0;// 更新UIui.progressBar->setValue(0);ui.statusLabel->setText("状态:运行中...0%");ui.startBtn->setEnabled(false);ui.stopBtn->setEnabled(true);// 提交后台任务m_taskFuture = QtConcurrent::run(this, &QtThreadMinDemo::backgroundTask);m_taskWatcher.setFuture(m_taskFuture);
}// 停止任务按钮回调
void QtThreadMinDemo::on_stopBtn_clicked()
{m_forceStop.store(true);if (m_taskFuture.isRunning()) {// 原子设置终止标志// 取消任务并等待线程退出m_taskFuture.cancel();m_taskFuture.waitForFinished();// 更新UIui.statusLabel->setText(QString("状态:已终止(进度%1%)").arg(m_currentProgress));}m_taskWatcher.disconnect();m_taskWatcher.setFuture(QFuture<bool>());// 恢复按钮状态ui.startBtn->setEnabled(true);ui.stopBtn->setEnabled(false);m_forceStop.store(false);
}// 后台任务(子线程执行)
bool QtThreadMinDemo::backgroundTask()
{qDebug() << "后台线程启动,ID:" << QThread::currentThreadId();// 模拟100步耗时计算for (int i = 0; i <= 100; ++i) {// 检查终止标志if (m_forceStop.load() || QThread::currentThread()->isInterruptionRequested()) {qDebug() << "后台线程被终止,当前进度:" << i;return false;}// 模拟耗时计算(无业务意义)volatile long long sum = 0;for (long long j = 0; j < 1000000; ++j) {// 检查终止标志if (m_forceStop.load() || QThread::currentThread()->isInterruptionRequested()) {qDebug() << "后台线程被终止,当前进度:" << i;return false;}sum += j;}// 保护共享进度数据{QMutexLocker locker(&m_progressMutex);m_currentProgress = i;}// 跨线程更新UIupdateProgress(i);// 控制任务速度QThread::msleep(50);}qDebug() << "后台线程完成,ID:" << QThread::currentThreadId();return true;
}// 跨线程更新进度UI
void QtThreadMinDemo::updateProgress(int progress)
{QMetaObject::invokeMethod(this, [this, progress]() {ui.progressBar->setValue(progress);ui.statusLabel->setText(QString("状态:运行中...%1%").arg(progress));}, Qt::QueuedConnection);
}// 任务完成回调(主线程)
void QtThreadMinDemo::on_taskFinished()
{bool success = m_taskWatcher.result();if (success) {ui.statusLabel->setText("状态:执行完成!");QMessageBox::information(this, "提示", "后台任务100%完成~");} else {ui.statusLabel->setText(QString("状态:执行中断(进度%1%)").arg(m_currentProgress));}ui.startBtn->setEnabled(true);ui.stopBtn->setEnabled(false);
}
#include "qtthreadmindemo.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QtThreadMinDemo w;w.show();return a.exec();
}

在这里插入图片描述

http://www.dtcms.com/a/609979.html

相关文章:

  • 做旅游景点网站的目的和意义怎么上传网站地图
  • 判断电脑和手机访问网站怎么选择郑州网站建设
  • Java的编译器是用什么语言写的 | 深入探讨Java编译器的实现原理与技术细节
  • 小麦高分子量谷蛋白(HMW-GS)完整提取流程
  • PostIn从初级到进阶(5) - 如何导入PostMan数据,实现数据迁移
  • LeetCode 面试经典 150_二叉树_二叉树展开为链表(74_114_C++_中等)
  • 航空电子全双工交换式以太网(Avionics Full DupleX switched Ethernet,AFDX)
  • 网站建设资费怎么做网站的浏览量统计
  • SpringBoot16-@Configuration 类
  • 【EGO-Planner自主无人机】在编译EGO-Planner源码时遇到的问题
  • 农业无人机实训教学转型—虚拟仿真破解“三高三难”
  • 专做五金正品的网站网站的定位分析
  • Android开发-java版:SQLite数据库
  • PHP进阶-在Ubuntu上搭建LAMP环境教程
  • 苔藓泛基因组--文献精读174
  • 购物网站建设过程视频权威发布信息
  • 网站建设营销方案wordpress添加微信分享功能
  • JavaWeb项目打包、部署至Tomcat并启动的全程指南(图文详解)
  • Netty和Tomcat有什么区别
  • 多标签页导航后台模板 html+css+js 纯手写 无第三方UI框架 复制粘贴即用
  • 做贷款网站犯法英文网站字体大小
  • Docker Desktop(Windows/Mac)零外网部署 Dify 极简指南
  • 1015 Reversible Primes
  • Nextcloud容器化部署新范式:Docker与Cpolar如何重塑私有云远程访问能力
  • 网站资源建设方案西安网页设计培训
  • AI Compass前沿速览:GPT--Codex 、宇树科技世界模型、InfiniteTalk美团数字人、ROMA多智能体框架、混元D .
  • 做维修那个网站发布信息好编辑不了的wordpress
  • 织梦摄影网站模板长沙网站制作公司怎么做
  • 《Chrome》 [142.0.7444.60][绿色便携版] 下载
  • leetcode2536. 子矩阵元素加 1