关于Boost Timer对象复用的技术咨询:移出循环后为何无法正常工作
如何复用Boost Timer 2实现周期性打印
哈哈,这个问题我之前也踩过坑!Boost Timer 2的定时器(比如asio::system_timer)默认是单次触发的——你把创建代码移出while(1)后,它只在第一次设置的过期时间点触发一次回调,之后就不会再自动触发了,所以程序看起来“没反应”。不过复用Timer对象完全可行,核心是要在每次触发后重新配置它的过期时间,下面给你两种常用的实现方式:
方式一:异步回调(推荐,非阻塞)
这种方式用Boost Asio的异步机制驱动,不需要手动写while(1)循环,更适合事件驱动的场景:
#include <iostream> #include <boost/asio.hpp> #include <chrono> using namespace boost::asio; using namespace std::chrono_literals; int main() { io_context io; // 把Timer对象放在循环外,只创建一次 system_timer timer(io, 1s); // 定义周期性打印的回调函数,捕获timer和io实现循环触发 auto periodic_print = [&](const boost::system::error_code& ec) { if (!ec) { std::cout << "周期性打印触发!" << std::endl; // 关键步骤:重新设置下一次触发的时间 timer.expires_after(1s); // 再次注册回调,实现循环 timer.async_wait(periodic_print); } }; // 启动第一次定时器 timer.async_wait(periodic_print); // 让io_context运行起来,处理异步事件 io.run(); return 0; }
核心逻辑:
- Timer对象只初始化一次,复用同一个实例
- 每次回调执行完后,调用
expires_after()重新设置下一次触发的间隔 - 通过
async_wait()再次注册回调,形成循环触发的闭环 io.run()会持续运行,处理定时器的异步事件,不需要手动写阻塞循环
方式二:同步等待(简单阻塞)
如果你习惯用while(1)的阻塞写法,也可以复用Timer对象,只需要每次循环前重新设置过期时间:
#include <iostream> #include <boost/asio.hpp> #include <chrono> using namespace boost::asio; using namespace std::chrono_literals; int main() { io_context io; // 复用这个Timer对象,只创建一次 system_timer timer(io); while (true) { // 每次循环前设置新的过期时间 timer.expires_after(1s); // 同步等待定时器触发 timer.wait(); std::cout << "周期性打印触发!" << std::endl; } return 0; }
核心逻辑:
- Timer对象在循环外创建,每次循环中只更新过期时间
timer.wait()会阻塞到过期时间到达,触发后执行打印,然后进入下一次循环重新设置时间
关键总结
- Boost Timer 2的定时器完全可以复用,不要每次循环都创建新对象(既浪费资源,也没必要)
- 不管是异步还是同步方式,核心都是每次触发后/循环前重新设置过期时间
- 异步方式更高效,适合复杂的事件驱动程序;同步方式简单直观,适合小型脚本或简单场景
内容的提问来源于stack exchange,提问作者CaTx
相关产品推荐
相关产品推荐

