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

工作线程快速优雅退出方式探讨

本文我们不用定时器。定时器会阻塞消息循环。先看需求:

我们先看第一种,有一个任务,要求每1秒钟执行一次,最常见的写法如下两种


bool bExitThread = false;
DWORD WorkThread1(LPVOID param)
{while (false == bExitThread){//// to-do 这里是执行任务的具体代码//Sleep(1000);}return 0;
}

或者如下:

HANDLE hEventExit = ::CreateEvent(NULL, FALSE, FALSE, _T("hEventExit"));DWORD WorkThread1(LPVOID param)
{while (false == bExitThread){DWORD nRet = ::WaitForSingleObject(hEventExit, 1000);if (WAIT_TIMEOUT != nRet){break;}////to-do 执行任务具体代码//}return 0;
}

勉强可以用了,但是有明显缺点,是当软件要退出时,必须等待该线程1秒钟,非常不实时。无法完成快速响应退出。很致命啊。

于是有了改进的写法,如下两种:


DWORD WorkThread2(LPVOID param)
{while (false == bExitThread){//// to-do 这里是具体代码//for (int i = 0; i < 100; i++){Sleep(10);if (bExitThread)break;}}return 0;
}

或者如下:

HANDLE hEventExit = ::CreateEvent(NULL, FALSE, FALSE, _T("hEventExit"));DWORD WorkThread1(LPVOID param)
{DWORD nCount = 0;while (false == bExitThread){DWORD nRet = ::WaitForSingleObject(hEventExit, 10);if (WAIT_TIMEOUT != nRet){break;}nCount++;if (0 == nCount % 100){////to-do 执行任务具体代码//}}return 0;
}

不得不说,这两种改进方式,的确做到了1秒钟执行1次任务,也能做到当软件退出时,能极快速的退出该线程。不得不说这种化整为零的好方式,比前面第一种好了许多,甚至你可以直接把睡眠或等待改成1毫秒,就可以达到更低时延的快速退出线程。

但是,假如需求做一下调整,但有多个任务,比如3个任务需要执行,而且,
任务1,必须保证每1秒钟要执行一次(耗时忽略不计)
任务2,必须保证每2秒钟要执行一次(耗时忽略不计)
任务3,必须保证每3秒钟要执行一次(耗时忽略不计)

(不准使用定时器N个定时器,定时器会导致一顿一顿的,也不准开N个定时器再在里面各开1个线程), 我们怎么做到保证N个任务,按如上要求执行,还要能保证退出时,线程能最快的退出。

事实上这才是我们现实需求中最最常见的。这个时候,同样也可以用化整为零的多次Sleep或WaitForSingleObject来完成。比如如下,巧用nCount计数来完成:


HANDLE hEventExit = ::CreateEvent(NULL, FALSE, FALSE, _T("hEventExit"));DWORD WorkThread3(LPVOID param)
{bool bSet = false;DWORD nCount = 0;while (false == bExitThread){DWORD nRet = ::WaitForSingleObject(hEventExit, 1);if (WAIT_TIMEOUT != nRet){break;}nCount++;if (0 == nCount % 1000){//// to-do Task1//}if (0 == nCount % 2000){//// to-do Task2//}if (0 == nCount % 3000){//// to-do Task3//}}return 0;
}

显然是达到了多个任务都可以按照指定的时间间隔频次执行,而且还能做到软件退出时,该线程也能快速的退出。

但假如需求再变一下,只准开一个线程,3个任务需求同上,但是每个任务执行耗时不可忽略,任务执行耗时1秒却不可中断。这个时候,我们如何做到软件退出时,最快的退出呢?

显然软件正好退出时,可能该线程刚好进入任务N执行,执行1秒耗时不可中断,必然需要等待。

显然这个时候需要做到快速优雅的退出,就比较困难了。如果实在不想等待1秒的话,我们可以直接PauseThread或TerminateThread,来暂停或打断该线程的执行,然后退出软件。这也不失是一种快速响应退出线程的好方法了。

虽然可以做到快速退出了,但是有一个需求是没有满足的,那就是:

  • 每隔1秒执行一次Task1;
  • 每隔2秒执行一次Task2;
  • 每隔3秒执行一次Task3;

为什么呢,因为这种方式有个弊端,当第2秒时,Task1执行耗时1秒,它占了1秒,导致了Task2往后延了1秒执行;当第3秒时,Task2,Task3依次又顺延了许多秒,并没有达到需求。所以这个时候只准开1个线程,就很难实时满足需求了。只能改成开3个线程单独去处理了。

搁笔。如有疑问,站内信联系

相关文章:

工作线程快速优雅退出方式探讨

本文我们不用定时器。定时器会阻塞消息循环。先看需求&#xff1a; 我们先看第一种&#xff0c;有一个任务&#xff0c;要求每1秒钟执行一次&#xff0c;最常见的写法如下两种 bool bExitThread false; DWORD WorkThread1(LPVOID param) {while (false bExitThread){//// to…...

甘特图控件DHTMLX Gantt教程:用PHP:Laravel实现Gantt(上)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求&#xff0c;具备完善的甘特图图表库&#xff0c;功能强大&#xff0c;价格便宜&#xff0c;提供丰富而灵活的JavaScript API接口&#xff0c;与各种服务器端技术&am…...

ffmpeg-命令大全03

ffplay/mpv 查看所有的解码器 ffplay -decoders >>decoders.txt ffplay无延时无缓存播放 ffplay -fflags nobuffer -i "%1" ffplay指定size播放 ffplay -x 480 -y 270 -i "%1" ffplay指定解码器 ffplay -vcodec hevc_cuvid "%1" […...

MATLAB中太赫兹时域光谱的最大似然参数估计

目录 一、引言 二、最大似然估计的基本原理 三、MATLAB中的最大似然估计实现 四、太赫兹时域光谱的最大似然参数估计 五、结论 六、参考文献 一、引言 太赫兹波&#xff08;Terahertz wave&#xff09;是电磁谱中介于微波与光波之间的一段频率范围&#xff0c;频率大约在…...

详解MySQL的并发控制

目录 1.概述 2.事务 2.1.什么是事务 2.2.事务的隔离级别 2.2.1.三种数据一致性问题 2.2.2.四种隔离级别 2.3.如何设置隔离级别 3.锁 3.1.锁与事务的关系 3.2.分类 3.3.表锁 3.3.1.概述 3.3.2.读锁 3.3.3.写锁 3.3.4.保护机制 3.4.行锁 3.4.1.概述 3.4.2.什么…...

Android Termux安装MySQL数据库 | 公网安全远程连接【cpolar内网穿透】

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…...

SpringBoot的常见配置

SpringBoot基础配置 1. 配置文件格式问题导入1.1 修改服务器端口1.2 自动提示功能消失解决方案1.3 SpringBoot配置文件加载顺序 2. yaml问题导入2.1 yaml语法规则2.2 yaml数组数据2.3 yaml数据读取 3. 多环境开发配置问题导入3.1 多环境启动配置3.2 多环境启动命令格式3.3 多环…...

LabVIEWCompactRIO 开发指南25 实施LabVIEW FPGA代码的方法

LabVIEWCompactRIO 开发指南25 实施LabVIEW FPGA代码的方法 开始开发时&#xff0c;应在LabVIEW项目的FPGA目标下创建VI&#xff0c;以便使用LabVIEW FPGA选板进行编程&#xff0c;该选板是LabVIEW选板的子集&#xff0c;包括一些LabVIEW FPGA特定函数。 应该在仿真模式下开…...

如何利用Jmeter从0到1做一次完整的压测

压测&#xff0c;在很多项目中都有应用&#xff0c;是测试小伙伴必备的一项基本技能&#xff0c;刚好最近接手了一个小游戏的压测任务&#xff0c;一轮压测下来&#xff0c;颇有收获&#xff0c;赶紧记录下来&#xff0c;与大家分享一下&#xff0c;希望大家能少踩坑。 一、压测…...

蓝桥:前端开发笔面必刷题——Day1 数组(一)

文章目录 &#x1f4cb;前言&#x1f3af;数组中重复的数字&#x1f4da;题目内容✅解答 &#x1f3af;两数之和&#x1f4da;题目内容✅解答 &#x1f3af;替换空格&#x1f4da;题目内容✅解答 &#x1f3af;二维数组中的查找&#x1f4da;题目内容✅解答 &#x1f4dd;最后 …...

SQL 教程-入门基础篇

文章目录 SQL 简介SQL 语法SQL SELECT 语句SQL SELECT DISTINCT 语句SQL WHERE 子句SQL AND & OR 运算符SQL ORDER BY 关键字SQL INSERT INTO 语句SQL UPDATE 语句SQL DELETE 语句 SQL 简介 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理和操作关系…...

循环自相关函数和谱相关密度(六)——信号的循环平稳性(循环自相关函数)原理及推导

在通信、遥测、雷达和声纳系统中,一些人工信号是一类特殊的非平稳信号,它们的非平稳性表现为周期平稳性。通信信号常用待传输信号对周期性信号的某个参数进行调制、如对正弦载波进行调幅、调频和调相,以及对周期性脉冲信号进行脉幅、脉宽和脉位调制,都会产生具有周期平稳性…...

C/C++:04. 多态和虚函数

不加virtual&#xff0c;只能访问成员变量&#xff0c;不能访问成员函数 文章目录 前言1 虚函数与多态不用虚函数的多态使用虚函数的多态 2 C虚函数注意事项 构成多态的条件C虚函数注意事项构成多态的条件什么时候声明虚函数 3 C虚析构函数的必要性总结 前言 本节阐述C中的多态…...

拿下多个定点/比亚迪要上!这项技术要「降维打击」单目感知

2008年&#xff0c;斯巴鲁在全球首次推出了搭载有立体视觉摄像头的主动安全解决方案&#xff0c;并具有紧急制动功能的“EyeSight”。2010年&#xff0c;斯巴鲁推出升级版的“EyeSight”&#xff0c;成为世界上首个可以在全车速范围内避免碰撞的量产技术系统。 2014年&#xff…...

Go 的时间操作

Go 的时间操作 1. time 包 1.1. 时间类型 Go 语言中时间类型有两种&#xff1a; time.Time&#xff1a;表示时间的类型&#xff0c;常见的有两种方式&#xff1a; time.Now()&#xff1a;获取当前的时间time.Date()&#xff1a;根据指定的年、月、日、时、分、秒、纳秒等创…...

ThreeJS进阶之矩阵变换

ThreeJS的矩阵变换 Three.js使用matrix编码3D变换 —— 平移(位置),旋转和缩放。Object3D的每个实例都有一个matrix,用于存储该对象的位置,旋转和比例。这里介绍如何更新对象的变换。 三维物体(Object3D) 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对…...

分布式锁概念

什么是分布式锁 方案一&#xff1a;SETNX EXPIRE 方案二&#xff1a;SETNX value值是&#xff08;系统时间过期时间&#xff09; 方案三&#xff1a;使用Lua脚本(包含SETNX EXPIRE两条指令) 方案四&#xff1a;SET的扩展命令&#xff08;SET EX PX NX&#xff09; 方案五…...

PMP课堂模拟题目及解析(第10期)

91. 在项目执行阶段&#xff0c;一名项目干系人要求项目经理加入一个新过程的优化。项目经理应该怎么做&#xff1f; A. 执行实施整体变更控制过程。 B. 与过程专家一起审查项目。 C. 将优化项目分配给团队。 D. 拒绝范围蔓延企图。 92. 项目经理要求团队提供对项目应急计…...

Arm微架构分析系列3——Arm的X计划

1. 引言 前文介绍了Arm公司近几年在移动处理器市场推出的Cortex-A系列处理器。Cortex-A系列处理器每年迭代&#xff0c;性能和能效不断提升&#xff0c;是一款非常成功的产品。但是&#xff0c;Arm并不满足于Cortex-A系列每年的架构小幅度升级&#xff0c;又推出了X计划&#x…...

Kubernetes(K8S)的基础概念

文章目录 一、Kubernetes介绍1、什么是Kubernetes&#xff1f;2、为什么要用K8S?3、k8s的特性 二、k8s集群架构与组件1、Master组件2、配置存储中心——etcd3、Worker Node 组件 三、k8s核心概念●Pod●Pod 控制器(五大控制器)●Label●Label选择器(Label selector )●Service…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...