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

在QT中实现线程暂停

     

目录

一、实现方法

1)互斥锁实现暂停

2)条件等待类实现

二、总结


 QT本身并没有提供实现线程暂停的机制,可是在某些情况下,我们可能需要暂停线程的执行,暂停线程可能是用户手动暂停,也可能是在某些条件下暂停,且在暂停后可以随时继续线程的运行。下面介绍如何用QT实现线程暂停和继续。

一、实现方法

       在QT中并没有定义可以直接使线程暂停的函数或相关功能,通常清空下线程只有在完成所有工作后才会退出。若要在线程正在运行的过程中实现暂停,可以借用QT中的互斥锁来实现,或者使用条件等待两种方式。

1)互斥锁实现暂停

(1)实现思路

       互斥锁即使用QMutex类。QMutex通常用在线程同步中,也可借助QMutex类的特性实现线程暂停。首先定义一个QMutex对象mutex,mutex可被主线程和子线程访问,或多个线程访问。我们知道mutex只能同时被锁定一次。比如如果主线程调用lock()函数锁定了mutex,那么子线程再调用lock()锁定mutex时,子线程将会被阻塞,直到主线程调用unlock()解锁mutex后,子线程才会解除阻塞继续执行。因此,借用QMutex对象的锁定机制,我们就可以实现子线程的暂停和继续功能。

(2)代码示例

       首先我们在头文件中定义了一个QThread对象,在该类中申明了一个QMutex myLock锁,这个锁为public类型,便于被外部访问。

class PlayThread : public QThread
{Q_OBJECT
public:QMutex myLock;//定义一个互斥锁protected:void run();
};

       子线程的实现代码如下,我们定义了一个for循环,具体的业务代码在这个循环中实现。在业务逻辑的先后我们分别执行了对myLock的上锁和解锁过程。myLock.lock()用于上锁,也就是用于阻塞线程实现暂停的目的。在一次业务逻辑完成后执行myLock.unlock()解锁是非常有必要的,因为前面子线调用lock对该锁执行了上锁,那么子线程在业务执行完成后就必须要解锁,否则在子线的外部的主线程或其它线程将不能对myLock进行上锁,也就不能再实现暂停的功能,而且会导致外部线程被阻塞。所以,在此处子线程的业务完成后必须解锁。其实,为了更可靠的防止外部线程被阻塞,子线程可以在上锁后立即解锁,而不用等待业务执行完毕。

void PlayThread::run()
{for(courrentCount = primaryFrame; courrentCount < frameCount; courrentCount++){myLock.lock();readData();//读取数据myLock.unlock();}if(courrentCount == frameCount){primaryFrame = 0;courrentCount = 0;emit threadEnd();//发送线程结束信号}
}

2)条件等待类实现

(1)实现思路

       第二种实现方法是使用QWaitCondition类。QWaitCondition的核心是提供了两个方法,wait()和wakeOne()/wakeAll()。一个用于阻塞线程,一个用于唤醒线程,两个方法结合使用就可以实现线程的暂停和继续。首先我们需要定义一个QWaitCondition对象,该对象同样要被主线程和子线程访问,或多个线程访问。在被需要暂停的线程中我们调用wait()方法,用于阻塞线程,在其它线程中我们调用wake方法用于唤醒线程。

       wait()方法有两个重构方式,常用的是wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX)模式,两个参数分别是QMutex 和unsigned long类型。ULONG_MAX表示的是等待超时时间,默认情况下会永远等待。lockedMutex是一个互斥锁,在调用wait()函数时,会解锁该互斥锁。因此,在调用wait()函数前,我们必须要对lockedMutex进行上锁,而且上锁必须在该子线程中进行。

       唤醒方法同样有两个,wakeOne()和wakeAll()。QWaitCondition对象的wait()函数可以在多个子线程中被使用,wakeAll()顾名思义,唤醒所有调用了wait()函数的子线程,唤醒顺序是由操作系统来决定的,不可控。wakeOne()是唤醒一个子线程,如果存在多个子线程调用了QWaitCondition对象的wait()函数,那么唤醒的是哪一个子线程也是不可控的,因此要实现唤醒指定的子线程,目前只能通过为特定的子线程定义单独的QWaitCondition对象,以对象名称区分来实现。

(2)代码示例

       以下是子线程中的实现代码,mutex是一个互斥锁对象,首先在循环中对其进行上锁。keyPressed是一个QWaitCondition对象,上锁后即进入等待状态。在其它线程中调用keyPressed.wakeAll()或keyPressed。wakeOne()后即可唤醒该子线程,并继续执行后续业务工作。

  forever {mutex.lock();keyPressed.wait(&mutex);do_something();mutex.unlock();}

二、总结

        以上两种实现方案是QT中线程暂停的常用方法。其中通过条件等待类实现的方法形式相对比较简单,也易于理解,但是其不具备随时暂停的功能,子线程在每完成一次业务逻辑后均会进入阻塞状态,直到被唤醒,因此其灵活性不够,使用范围受限。第一种方法直接利用了互斥锁的阻塞机制,可随时暂停和继续,使用更加灵活。但是如果线程之间的关系把握不清的话容易超出内存访问冲突或死锁的情况,因此在使用时要准确分析业务逻辑。在大多数情况下,为了实现灵活性,更建议使用第一种方法。

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

相关文章:

  • vivado自定义IP显示只读解决办法
  • 当 AI 走进图像编辑:Bing 照片编辑器的实用价值与体验观察
  • Java Linux --- 基本命令,部署Java web程序到线上访问
  • 天安云谷网站建设企业邮箱忘记密码怎么找回
  • SQL 多表查询场景速查:一对一、一对多、多对多
  • 从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 7--基础知识 3--常用函数 1
  • Amazon S3 Vectors:向量存储、索引与多亚马逊云科技服务协同的智能桥梁解决方案
  • 第二章 prompt思维链
  • 大模型面经(一) Prompt + RAG + 微调
  • 第一章——了解prompt以及一些基础技巧方法
  • 做牛津布面料在哪个网站找客户找人一起做素材网站
  • 土豆家族工具使用适配表格大全【windows提权】
  • PyQt5 QPushButton组件详解:按钮控件的完整指南
  • Linux中do_wait函数的实现
  • 第1章 线程安全的对象生命期管理
  • Codeforces Round 1027 A. Square Year (2114)
  • 公司网站备案信息查询嵌入式开发培训
  • mysql--核心日志文件详解
  • 营销型网站要多少钱广告联盟app
  • 浙江建设职业技术学院官方网站中信建设有限责任公司资质等级
  • Vidmy 1.0.129| 无限制下载国外视频,支持高速下载、即时抓取高清视频。使用需要科学
  • (CVPR2025)DEIM模型训练自己的数据集教程(基于Pycharm)
  • 13.排序(上)
  • 《KelpBar海带Linux智慧屏项目》
  • 二叉树的层序遍历--力扣
  • 解决Linux下操作无权限问题——chmod: 正在更改...的权限:不允许的操作
  • 哈尔滨论坛建站模板ftp上传网站后怎么弄
  • 使用D3.js画人物关系图
  • 数据结构与算法篇--语义智能指针设计模式
  • 微信小程序入门学习教程,从入门到精通,WXML(WeiXin Markup Language)语法基础(8)