news 2026/8/29 3:49:42

一个支持暂停和继续的 C++ 时间管理类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一个支持暂停和继续的 C++ 时间管理类

前段时间在项目里碰到一个挺常见、但又特别容易写烂的需求:
统计时间。

听起来很简单,但一旦加上这几个条件,事情立刻变复杂:

  • 有一个总时间
  • 总时间由多个分段组成
  • 每个分段过程中可以暂停、恢复,而且可能不止一次
  • 暂停期间不能算有效时间

如果你随手用定时器或者不断累加,很快就会发现:
时间开始不对劲了。

要么多算了暂停时间,要么暂停几次之后就彻底乱套。

后来我索性停下来,重新想了一下:
时间这东西,真的有必要一直“加”吗?


换个思路:能算出来的,就别累加

最后我用的方案其实很简单:

  • 所有时间都用时间戳
  • 只在关键节点结算
  • 其余时候全部“现算”

于是就有了下面这个TimeManager


先上代码(核心就这些)

先写一个获取当前秒时间戳的小工具,用的是 C++ 自带的std::chrono

#include<chrono>staticuint64_tgetNowSeconds(){returnstd::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();}

然后是整个时间管理类:

classTimeManager{public:TimeManager():totalTime(0),segmentStartTime(0),segmentPauseTotal(0),totalPauseTotal(0),pauseStartTime(0),isPaused(false){}voidstartSegment(){segmentStartTime=getNowSeconds();segmentPauseTotal=0;isPaused=false;pauseStartTime=0;}voidpause(){if(isPaused||segmentStartTime==0)return;isPaused=true;pauseStartTime=getNowSeconds();}voidresume(){if(!isPaused||pauseStartTime==0)return;uint64_tnow=getNowSeconds();uint64_tpauseDuration=now-pauseStartTime;segmentPauseTotal+=pauseDuration;totalPauseTotal+=pauseDuration;isPaused=false;pauseStartTime=0;}voidstopSegment(){if(segmentStartTime==0)return;totalTime+=getSegmentTime();segmentStartTime=0;segmentPauseTotal=0;isPaused=false;pauseStartTime=0;}uint64_tgetSegmentTime()const{if(segmentStartTime==0)return0;uint64_tendTime=isPaused?pauseStartTime:getNowSeconds();returnendTime-segmentStartTime-segmentPauseTotal;}uint64_tgetTotalTime()const{returntotalTime+getSegmentTime();}private:uint64_ttotalTime;uint64_tsegmentStartTime;uint64_tsegmentPauseTotal;uint64_ttotalPauseTotal;uint64_tpauseStartTime;boolisPaused;};

代码不长,但逻辑我挺满意的。


这个类到底在干什么?

一句话概括就是:

总时间 = 已结束分段的时间 + 当前分段实时算出来的时间

这里有几个我刻意分开的概念。


1️⃣ 总时间是“已经记账的时间”

uint64_ttotalTime;

这个值只在一个地方改:
stopSegment()

也就是说,只有当我明确“这个分段结束了”,
它的有效时间才会被加到总时间里。

中途暂停、恢复、怎么折腾,都不碰它。


2️⃣ 分段时间永远不累加,全部现算

分段有效时间的公式其实很直白:

当前时间 - 分段开始时间 - 分段暂停时间

对应的代码就是:

uint64_tendTime=isPaused?pauseStartTime:getNowSeconds();returnendTime-segmentStartTime-segmentPauseTotal;

有一个细节我当时特意处理了:
如果正在暂停,时间直接冻结。

所以暂停多久,分段时间就真的一秒都不涨。


3️⃣ 暂停时间只在恢复那一刻结算

我见过不少代码,是在 pause 的时候就开始各种计算,
最后状态一多就完全兜不住。

我这里的逻辑很简单:

  • pause:只记一个时间点
  • resume:统一算这次暂停了多久
uint64_tpauseDuration=now-pauseStartTime;segmentPauseTotal+=pauseDuration;

这样不管你暂停多少次,都不会乱。


实际用起来是什么感觉?

比如这样一段流程:

TimeManager tm;tm.startSegment();// 干活// 10 秒tm.pause();// 停一下// 5 秒tm.resume();// 接着干// 8 秒tm.stopSegment();// 收工

最后得到的结果是:

  • 有效时间:18 秒
  • 暂停时间:5 秒
  • 总时间只加了 18 秒

暂停没有“偷”走任何有效时间。


写完之后的一个感受

时间统计这东西,最怕的不是代码写得少,而是状态太多。

后来我发现,只要记住一句话,问题就好解决很多:

能用时间戳算出来的,就别用变量去维护。

这个TimeManager本质上不是计时器,
而是一个时间状态管理器

如果你做的是:

  • 任务耗时统计
  • 工单 / 流程时间分析
  • 设备运行时间管理

这种思路基本都能直接套。


如果你对那些功能更感兴趣,也可以留言告诉我。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 2:16:34

宾夕法尼亚州立大学团队:让AI系统学会自己进化

这项由宾夕法尼亚州立大学、亚马逊和杜克大学联合开展的研究发表于2026年2月&#xff0c;论文编号为arXiv:2602.00359v1&#xff0c;有兴趣深入了解的读者可以通过该编号查询完整论文。这项研究提出了一个让人眼前一亮的想法&#xff1a;让AI系统学会自己进化&#xff0c;就像生…

作者头像 李华
网站建设 2026/8/26 11:35:31

Qt之多线程和并发_P2

在使用多线程时需要时刻注意一点的时,多个线程在访问同一个资源时会抢夺资源,造成数据不一致,严重影响程序结果甚至崩溃。为了防止竞态条件的发生,使用多线程时需要实现线程同步,也即确保多个线程在同时使用共享资源时不会发生冲突或数据不一致。 Qt提供了互斥锁、信号量、…

作者头像 李华
网站建设 2026/8/27 13:20:29

科研党收藏!自考必备的AI论文工具 —— 千笔写作工具

你是否在论文写作中经常感到无从下手&#xff1f;选题纠结、思路混乱、查重率高、格式出错……这些难题是否让你夜不能寐&#xff1f;对于自考学生来说&#xff0c;论文不仅是毕业的关键&#xff0c;更是对学术能力的终极考验。而如今&#xff0c;有了千笔AI&#xff0c;这一切…

作者头像 李华
网站建设 2026/8/29 0:26:06

Redis与MySQL回写中的数据类型存储设计

一、前置 在 Redis 与 MySQL 数据回写场景中&#xff0c;Redis 核心定位是缓存 / 高效存储层&#xff0c;MySQL 是持久化存储层&#xff0c;数据回写通常是「Redis 更新→同步 / 异步更新 MySQL」或「MySQL 更新→刷新 Redis」。KV 设计需遵循 3 个通用原则&#xff1a; 1. 键…

作者头像 李华
网站建设 2026/8/29 1:04:58

寒假集训7——STL

P3370 【模板】字符串哈希 题目描述 如题&#xff0c;给定 N 个字符串&#xff08;第 i 个字符串长度为 Mi​&#xff0c;字符串内包含数字、大小写字母&#xff0c;大小写敏感&#xff09;&#xff0c;请求出 N 个字符串中共有多少个不同的字符串。 友情提醒&#xff1a;如…

作者头像 李华