std::this_thread::sleep_for仅适用于单次阻塞延时,不支持周期触发或异步回调;需用std::chrono::duration传参,windows精度约15ms。

std::this_thread::sleep_for 适合单次延时,但不是定时器
它只是让当前线程暂停一段时间,不支持周期性触发、也不支持异步回调。如果你只是想“3秒后打印一行字”,用它最轻量;但想“每5秒检查一次文件是否存在”,它就不够用了。
常见错误现象:std::this_thread::sleep_for 被误放在循环里却没考虑精度漂移,或者在 GUI 主线程里直接调用导致界面冻结。
- 只适用于阻塞式、单次、非实时要求的延时(比如模拟网络延迟)
- 参数是
std::chrono::duration,别传毫秒整数——写成sleep_for(1000)会编译失败,得写sleep_for(std::chrono::milliseconds(1000)) - 在 Windows 上最小精度约 15ms,Linux 可能更准,但别依赖亚毫秒级响应
std::thread + std::condition_variable 实现简易可取消定时器
这是 C++11 标准下最可控的手动方案:用一个后台线程等待,用条件变量做唤醒和取消。比 sleep_for 多一层封装,但完全不依赖第三方库。
使用场景:需要启动/停止控制、支持提前终止、任务执行时间短且不频繁(比如心跳上报、配置轮询)。
立即学习“C++免费学习笔记(深入)”;
- 核心是用
std::mutex保护一个bool stop_requested标志位 - 等待时调用
cv.wait_for(lock, duration, []{ return stop_requested; }),这样中断信号能立刻生效 - 别在线程函数里直接调用耗时操作——如果回调函数执行超过间隔时间,下一次触发会被挤压,甚至堆积
Windows 下用 SetTimer 需要消息循环,Linux 下没对应物
SetTimer 是 Win32 API,本质是往窗口消息队列投递 WM_TIMER,所以你必须有运行中的消息循环(GetMessage+DispatchMessage),否则定时器永远不会触发。
常见错误现象:控制台程序调用 SetTimer 却收不到回调,或回调函数里调用 std::cout 导致崩溃(GDI/控制台句柄跨线程问题)。
- 不能用于无窗口、无消息循环的环境(比如多数服务进程或 CLI 工具)
- 回调函数运行在 UI 线程,禁止做阻塞操作(如文件读写、网络请求)
- Linux 没有等价机制,别试图移植
SetTimer代码,换用timerfd_create或跨平台库
用 Boost.Asio 的 steady_timer 最接近“理想定时器”
如果你能引入 Boost,boost::asio::steady_timer 是目前 C++ 生态中最简洁、可靠、可组合的定时器实现。它基于系统底层(epoll/kqueue/iocp),支持重复、取消、绑定任意 callable,并天然适配异步模型。
性能影响:首次初始化 io_context 有轻微开销,但后续定时器创建/销毁几乎零分配;比手写线程+条件变量更省内存、更少上下文切换。
- 记得调用
io_context.run()启动事件循环,否则定时器永远不触发 - 重复定时器要手动在回调里调用
timer.expires_after(...); timer.async_wait(...) - 不要把
steady_timer对象分配在栈上然后异步触发——回调执行时对象可能已析构,用std::shared_ptr管理生命周期







