0

0

如何在C++中实现一个轻量级的定时器?(回调函数)

穿越時空

穿越時空

发布时间:2026-03-11 17:22:03

|

579人浏览过

|

来源于php中文网

原创

不能直接当定时器用,它只是时间工具;需自行实现循环、超时判断和回调调度,否则易出现精度偏差、线程不安全、ui崩溃、资源耗尽及悬垂引用等严重问题。

如何在c++中实现一个轻量级的定时器?(回调函数)

std::chrono + std::thread 能否直接做定时器?

不能直接当「定时器」用,它只是时间工具。你得自己搭循环、判断超时、调回调——容易漏掉精度控制和线程安全问题。

常见错误现象:std::this_thread::sleep_for 睡太久或太短,尤其在系统负载高时偏差可达几十毫秒;回调在子线程执行,但用户代码假设在主线程里改 UI 或访问 std::vector,结果崩得无声无息。

  • 别用 while (true) + sleep_for 做长周期定时(比如 5 分钟),系统休眠或调度延迟会让下次触发严重偏移
  • 如果回调要访问共享数据,必须加锁,或改用 std::atomic 保护简单标志位
  • 优先用 std::chrono::steady_clock,不用 system_clock——后者可能被 NTP 调整,导致“时间倒流”误判超时

如何避免重复创建线程开销?

每次 setTimer 都 new 一个 std::thread,短周期高频定时(如 10ms)会迅速耗尽线程资源,甚至触发 std::system_error: Resource temporarily unavailable

正确做法是复用单个后台线程,靠队列驱动多个定时任务:

立即学习C++免费学习笔记(深入)”;

  • std::priority_queue 存待触发的定时器,按唤醒时间排序,顶部是最先要触发的
  • 后台线程只做一件事:等最近那个定时器到期,pop 出来,调回调,再 loop
  • 插入新定时器时用 std::condition_variable::notify_one() 唤醒等待中的线程,避免死等

示例关键逻辑:

纳米漫剧流水线
纳米漫剧流水线

360推出的国内首个工业级AI漫剧生产平台

下载
auto now = std::chrono::steady_clock::now();
auto when = now + std::chrono::milliseconds(100);
timer_queue.push({when, []{ /* callback */ }});
cv.notify_one(); // 唤醒空闲线程

std::function 捕获变量后生命周期怎么管?

这是最常踩的坑:回调里用了局部变量的引用或指针,定时器还没触发函数就返回了,回调一执行就 UB。

典型错误写法:

void start_timer() {
    int value = 42;
    timer.set(1000, [&value]{ printf("%d\n", value); }); // 危险!
}

安全做法只有两种:

  • 值捕获全部依赖项:[value]{ printf("%d\n", value); }(适合小对象、可拷贝)
  • std::shared_ptr 包裹大对象,回调捕获该智能指针:[ptr = shared_from_this()]{ ptr->do_work(); }
  • 绝对不要捕获栈上容器的迭代器、std::string::c_str() 返回的指针——它们随局部变量销毁而失效

Windows 下 Sleep(1) 为什么不准?

不是 C++ 问题,是 Windows 内核默认时间粒度为 15.6ms。即使你 sleep_for(1ms),实际可能睡 16ms,累积误差极大。

解决办法有限但有效:

  • 调一次 timeBeginPeriod(1)(需 #include <windows.h></windows.h>),提升系统计时精度到 1ms(注意:影响全局,退出前配对调 timeEndPeriod(1)
  • Linux/macOS 不需要这步,nanosleepclock_nanosleep 默认支持 sub-ms 精度
  • 若只需“大约”精度(如心跳包 30s ± 1s),干脆别纠结 1ms,用 sleep_for(30s) 更稳

复杂点在于:跨平台时,精度控制、线程唤醒机制、回调执行上下文都得隔离。轻量 ≠ 简单,真正可靠的定时器哪怕只有 200 行,也得把 clock、queue、lifecycle、cancel 逻辑全兜住。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2023.12.20

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

106

2023.09.25

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

76

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

304

2023.11.28

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

764

2023.08.10

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.1万人学习

C 教程
C 教程

共75课时 | 5.3万人学习

C++教程
C++教程

共115课时 | 21.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号