Qt - 多线程之线程的开始、暂停、恢复、停止

news/2024/12/25 14:04:36/文章来源:https://www.cnblogs.com/zhuchunlin/p/18558406

示例1

在Qt中,可以使用QThread的线程控制功能来暂停和恢复一个线程。这里是一个简单的例子:

 
#include <QThread>
#include <QDebug>class WorkerThread : public QThread {void run() override {qDebug() << "Thread is running";// 执行一些任务for (int i = 0; i < 5; ++i) {msleep(1000); // 模拟工作if (isInterruptionRequested()) {qDebug() << "Thread is interrupted";return;}}qDebug() << "Thread is finished";}
};void pauseThread(QThread* thread) {thread->requestInterruption(); // 请求暂停while (thread->isRunning()) {// 等待线程暂停}
}void resumeThread(QThread* thread) {thread->start(); // 重新开始线程
}int main() {WorkerThread thread;thread.start();// 假设需要暂停线程pauseThread(&thread);// 假设在这里做一些其他的事情// 现在我们要恢复线程resumeThread(&thread);// 等待线程结束thread.wait();return 0;
}

在这个例子中,我们定义了一个WorkerThread类,它是QThread的子类,并且在run函数中执行了一些模拟任务。我们使用requestInterruption()来请求暂停线程,并且在run函数中检查isInterruptionRequested()来决定是否退出。

pauseThread函数请求暂停并且循环等待线程真正暂停。resumeThread函数则简单地重新开始线程。在main函数中,我们创建了一个WorkerThread对象,启动了线程,然后调用pauseThread来暂停它,接着我们可以恢复线程。

请注意,这个例子是为了演示如何暂停和恢复线程。在实际应用中,请确保你不会因为暂停一个线程而导致数据不一致或者其他的线程安全问题。此外,这种方法不适用于那些已经在等待事件发生的线程,因为在等待期间线程不会检查中断请求。

 

 

示例2

示例2是根据示例1优化之后的代码

项目目录结构:

mythread.h

 
#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>class Widget;class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(Widget* wid,QObject *parent = nullptr);~MyThread();protected:void run() override;private:Widget* m_wid;int m_pRecordingFlag;signals:
};#endif // MYTHREAD_H

mythread.cpp

 
#include "mythread.h"
#include <QDebug>
#include "widget.h"MyThread::MyThread(Widget* wid, QObject *parent): QThread(parent)
{m_wid = wid;m_pRecordingFlag = 1;
}MyThread::~MyThread()
{qDebug()<<   "MyThread::~MyThread()";
}void MyThread::run()
{qDebug() << "当前线程对象的地址: " << QThread::currentThread();while (1){if (28 < m_pRecordingFlag){m_pRecordingFlag = 1;}qDebug() << "m_pRecordingFlag = "<<m_pRecordingFlag;m_wid->loadPixmap(m_pRecordingFlag);m_wid->setPixmap();QThread::msleep(100);m_pRecordingFlag++;if (isInterruptionRequested()){qDebug() << "Thread is interrupted";return;}}
}

widget.h

 
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "mythread.h"#include <QLabel>
#include <QPixmap>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void pauseThread(QThread* thread);void resumeThread(QThread* thread);void loadPixmap(int flag);void setPixmap();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();private:Ui::Widget *ui;MyThread* mythread;QPixmap m_Pixmap;QLabel* m_Label;
};
#endif // WIDGET_H

widget.cpp

 
#include "widget.h"
#include "ui_widget.h"#include<QDebug>
#include<QThread>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);m_Label = new QLabel(this);m_Label->setFixedSize(760,140);//m_Label->setText("fdsf9999999999999");m_Label->setScaledContents(true);//设置内容缩放mythread = new MyThread(this,this);//创建线程connect(mythread,&QThread::started,this,[](){qDebug()<<"start";});connect(mythread,&QThread::finished,this,[](){qDebug()<<"finished";});qDebug() << "主线程对象的地址: " << QThread::currentThread();}Widget::~Widget()
{mythread->quit();//退出线程delete mythread;delete ui;
}void Widget::pauseThread(QThread* thread)
{thread->requestInterruption(); // 请求暂停while (thread->isRunning()){// 等待线程暂停}
}void Widget::resumeThread(QThread* thread)
{thread->start(); // 重新开始线程
}void Widget::on_pushButton_clicked()
{resumeThread(mythread);
}void Widget::on_pushButton_2_clicked()
{pauseThread(mythread);
}void Widget::loadPixmap(int flag)
{m_Pixmap.load(QString(":/recording/recording_%1.png").arg(flag));
}void Widget::setPixmap()
{m_Label->setPixmap(m_Pixmap);
}

运行效果:

 

 

示例3

一.前言

软件开发中,使用到线程就不可避免的要实现线程的暂停恢复停止等操作,总不可能说线程一旦启动就直接运行到结束了,中途不能停止啥的。线程的开始以及结束都比较简单,都有对应的接口可以调用,线程的暂停以及恢复就需要自己手动写个接口,关键在于使用线程锁来实现这个过程。

二.实现过程

1.1先继承QThread实现自己的线程类,声明线程锁变量,以及暂停恢复停止的接口

1.2核心代码(thread3.h)

 
/** 线程开始 暂停 恢复 停止 例程* V1.0 2021-12-27
*/#ifndef THREAD3_H
#define THREAD3_H#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTime>
#include <QCoreApplication>
#include <QMutex>class Thread3 : public QThread
{
public:Thread3();~Thread3(){}public:void close();void pauseThread();void resumeThread();protected:void run();private:volatile bool stop;bool pause;//作为线程状态的一个记录QMutex pauseLock;int i;
};#endif // THREAD3_H

 

1.3其他说明

增加关键字volatile是为了:提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,就会出现不一致的现象

2.核心代码(thread3.cpp)

 
#include "Thread3.h"Thread3::Thread3()
{stop=false;pause=false;i=0;
}void Thread3::close()
{stop=true;quit();wait();
}void Thread3::pauseThread()
{qDebug()<<"pauseThread";this->pauseLock.lock();pause=true;
}void Thread3::resumeThread()
{qDebug()<<"resumeThread";this->pauseLock.unlock();pause=false;
}void Thread3::run()
{while(i<10){if(!stop){// 线程锁在业务开始和和结束的地方pauseLock.lock();// 具体的业务逻辑i++;qDebug()<<i<<"-"<<QTime::currentTime()<<"-"<<"CurrnetThreadID:"<<QThread::currentThreadId();msleep(1000);//pauseLock.unlock();}else{break;}}
}

3.1核心代码 (widget.h)

 
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "thread3.h"QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();void on_pushButton_4_clicked();private:Ui::Widget *ui;Thread3* thread;
};
#endif // WIDGET_H

3.2核心代码 (widget.cpp)

 
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);qDebug()<<"主线程ID:"<<QThread::currentThreadId();thread = new Thread3();//创建线程}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_1_clicked()
{qDebug()<<"线程开始";thread->start();
}void Widget::on_pushButton_2_clicked()
{qDebug()<<"线程暂停";thread->pauseThread();
}void Widget::on_pushButton_3_clicked()
{qDebug()<<"线程恢复";thread->resumeThread();
}void Widget::on_pushButton_4_clicked()
{qDebug()<<"线程停止";thread->close();
}

 

3.3效果预览

 

三.其他

1.本文只是简单实现线程的开始暂停恢复以及停止功能,但是实际运用过程中,还需要增加诸多的逻辑处理,比如暂停之前判断线程的状态再执行,恢复之前判断线程的状态再执行恢复等

 

 

——————————————

原文链接:https://blog.csdn.net/Joker__123/article/details/122165065

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/837355.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux学习day03_linux文件与目录管理

1、相对路径和绝对路径的区别 绝对路径:路径的写法“一定由根目录 / 写起”,例如: /usr/share/doc 这个目录。相对路径:路径的写法“不是由 / 写起”,例如由 /usr/share/doc 要到 /usr/share/man 下面 时,可以写成: “cd ../man”这就是相对路径的写法啦!相对路径意指“…

我为什么要舍弃CSDN改用博客园

作为博客园老用户,我希望更加积极的在博客园分享技术而非CSDN,因为CSDN没有开放性,什么都要审核着实很烦! 下面是我在CSDN十余年耕耘,仅收获了一堆无用的破勋章和一万多粉丝,因为不怎么回消息答疑铁粉很少。下面是我跟CSDN在线客服的对话: 下面是客服回复给我的原文:抱…

Qt - 多线程之线程同步

一、线程为什么要同步 使用两个线程对一个全局变量做累加,从0加到10,所以只要每个线程累加到5就行。代码如下所示: #include <QApplication> #include <QThread> #include <QDebug>// 定义共享资源 int sharedValue = 0;// 定义一个线程类 class MyThread…

el-input 输入框加%号后缀

<el-input><i slot="suffix">%</i> </el-input> 如图学如逆水行舟,不进则退

人工智能之机器学习线代基础——克拉默法则(Cramers Rule)

克拉默法则是一种用于解 线性方程组 的方法,适用于系数矩阵为 方阵 的情况(即未知数的个数与方程的个数相等)。它通过计算行列式直接求解方程组的解。 克拉默法则的优缺点 优点直接性:可以显式地通过行列式计算出解。 理论价值:适合小规模问题,易于理解和验证解的正确性…

CommonsBeanUtils1(基于ysoserial)

环境准备 JDK1.8(8u421) JDK8的版本应该都没什么影响,这里直接以我的镜像为准了、commons-beanutils:commons-beanutils:1.9.2、commons-collections:commons-collections:3.2、javassist:javassist:3.12.0.GA mvn中加入以下依赖: <dependency><groupId>commons-…

【Mastercam 2025下载与安装教程 含补丁】

mastercam 2025是一款专门用于数控加工的软件,广泛应用于航空、汽车、机械制造等领域可以帮助工程师、机械加工师等专业人员高效地进行零件的建模和加工,提高生产效益和质量。 系统要求‌操作系统‌:Windows 7或更高版本,64位操作系统。 ‌处理器‌:CPU频率至少为2GHz。 ‌内…

《刚刚问世》系列初窥篇-Java+Playwright自动化测试-5-创建首个自动化脚本(详细教程)

1.简介 前面几篇宏哥介绍了两种(java和maven)环境搭建和浏览器的启动方法,这篇文章宏哥将要介绍第一个自动化测试脚本。前边环境都搭建成功了,浏览器也驱动成功了,那么我们不着急学习其他内容,首先宏哥搭建好的环境中创建首个完整的自动化测试脚本,让小伙伴或者童鞋们提…

2024年腾讯云双十一薅羊毛最强攻略:错过一次又得等一年!

2024年腾讯云双十一活动为用户提供了丰富的云产品和优惠福利,以下是一份省钱、省心、省力的购买攻略,帮助大家制定必抢清单: 一、活动时间与入口活动时间:即日起至2024年11月30日23:59:59,具体以页面变更为准。 活动入口:腾讯云双十一活动页面二、优惠活动概览 1.服务器限…

BGP路由控制

BGP路由控制概述 BGP协议的重点不在于发现和计算路由,而在于通过丰富的属性和策略实现对路由的控制。 控制BGP路由可以通过两种方式实现。 一是通过BGP 的基本属性实现对BGP 选路的控制。这种方式比较简单,主要是通过配置、修改BGP 基本属性值以影响协议的选路,从而实现控制…

Windows右键新建列表排序

前言全局说明Windows右键新建列表排序一、说明 环境: Windows 11 家庭版 23H2 22631.3737二、Windows11 右键新建列表排序 2.1 打开注册表项 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\ShellNew2.2 编辑 Classes 键 调整成…

如何让领导轻松在本地查看Allure报告

如何让领导轻松在本地查看Allure报告 问题描述 当我们把精心生成的Allure报告原始文件发送给领导后,领导直接打开index.html文件时,页面却一直处于加载状态,无法显示数据。通过F12开发者工具检查,我们发现这是由于浏览器跨域请求问题导致的。具体来说,当尝试通过XMLHttpRe…