IO服务重新启动后,Boost最后期限计时器持续触发
Boost deadline timer fires continuously after IO service restart
我正在编写一些命令代码,对此我需要一个常规计时器进行监控。我使用boost ASIO进行通信,所以我决定使用最后期限计时器进行计时,并将其放在同一个IO服务上。
第一次运行代码时一切都很好,但一旦通信(在我的情况下是串行端口(停止并重新启动,就会出错。计时器开始失灵,通讯中断。我相信这两者是相关的,所以我只关注这个问题的计时器。
请考虑下面的代码。这应该启动一个计时器,让它运行10秒,停止计时器,然后再启动它10秒。然而,实际发生的情况是,当计时器重新启动时,它会连续启动(两次启动之间没有任何延迟(。
#include <iostream>
#include <thread>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
boost::posix_time::ptime timer_start_;
void CallbackTimerFunc(boost::asio::deadline_timer* timer) {
auto time_since_start = timer->expires_at() - timer_start_;
std::cout << "It's been " << time_since_start.total_seconds() << " seconds." << std::endl;
// Sleep is here to prevent spamming when timer starts malfunctioning.
usleep(20000);
timer->expires_at(timer->expires_at() + boost::posix_time::milliseconds(1000));
timer->async_wait(boost::bind(&CallbackTimerFunc, timer));
}
int main(int /*argc*/, char** /*args*/) {
// Start
boost::asio::io_service io_service_;
boost::asio::deadline_timer deadline_timer_(io_service_);
deadline_timer_.expires_from_now(boost::posix_time::milliseconds(1000));
timer_start_ = deadline_timer_.expires_at();
deadline_timer_.async_wait(boost::bind(&CallbackTimerFunc, &deadline_timer_));
std::thread io_thread_(boost::bind(&boost::asio::io_service::run, &io_service_));
// Stop
sleep(10);
io_service_.stop();
while (!io_service_.stopped()) usleep(10000);
deadline_timer_.cancel();
io_thread_.join();
std::cout << "******************************" << std::endl;
// Restart
io_service_.restart();
deadline_timer_.expires_from_now(boost::posix_time::milliseconds(1000));
timer_start_ = deadline_timer_.expires_at();
deadline_timer_.async_wait(boost::bind(&CallbackTimerFunc, &deadline_timer_));
io_thread_ = std::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
// Stop
sleep(10);
io_service_.stop();
while (!io_service_.stopped()) usleep(10000);
deadline_timer_.cancel();
io_thread_.join();
return 0;
}
预期的输出是计时器两次计数到10(实际上是从0到8(。实际输出是,它一次计数到10,然后就失控了,声称数百秒已经过去了。
我可以通过创建一个全新的IO服务和计时器来让这些代码发挥作用,但考虑到它们应该是可重用的,这似乎没有必要。
如果有人能告诉我这里发生了什么,或者至少能重现我的结果,我将不胜感激
感谢@tkausl让我走上正轨。这是更正后的代码。注意CallbackTimerFunc
顶部的额外检查。
#include <iostream>
#include <thread>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
boost::posix_time::ptime timer_start_;
void CallbackTimerFunc(const boost::system::error_code& error, boost::asio::deadline_timer* timer) {
if (error.value() == boost::asio::error::operation_aborted) {
std::cout << "Abort was sent on the first firing. Because of course it would be. Ignoring it will fix the problem. Because of course it will." << std::endl;
return;
}
auto time_since_start = timer->expires_at() - timer_start_;
std::cout << "It's been " << time_since_start.total_seconds() << " seconds." << std::endl;
// Sleep is here to prevent spamming when timer starts malfunctioning.
usleep(20000);
timer->expires_at(timer->expires_at() + boost::posix_time::milliseconds(1000));
timer->async_wait(boost::bind(&CallbackTimerFunc, boost::asio::placeholders::error, timer));
}
int main(int /*argc*/, char** /*args*/) {
// Start
boost::asio::io_service io_service_;
boost::asio::deadline_timer deadline_timer_(io_service_);
deadline_timer_.expires_from_now(boost::posix_time::milliseconds(1000));
timer_start_ = deadline_timer_.expires_at();
deadline_timer_.async_wait(boost::bind(CallbackTimerFunc, boost::asio::placeholders::error, &deadline_timer_));
std::thread io_thread_(boost::bind(&boost::asio::io_service::run, &io_service_));
// Stop
sleep(10);
io_service_.stop();
while (!io_service_.stopped()) usleep(10000);
deadline_timer_.cancel();
io_thread_.join();
std::cout << "******************************" << std::endl;
// Restart
io_service_.restart();
deadline_timer_.expires_from_now(boost::posix_time::milliseconds(1000));
timer_start_ = deadline_timer_.expires_at();
deadline_timer_.async_wait(boost::bind(CallbackTimerFunc, boost::asio::placeholders::error, &deadline_timer_));
io_thread_ = std::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
// Stop
sleep(10);
io_service_.stop();
while (!io_service_.stopped()) usleep(10000);
deadline_timer_.cancel();
io_thread_.join();
return 0;
}
相关文章:
- Linux的Cpp上的计时器
- 提升 ASIO 无法识别计时器对象
- 提升 asio 并发计时器取消问题与链
- 使用单体计时器的pthread_cond_timedwait有时会比预期晚超时
- 窗口中的微秒计时器
- 计时器是否从另一个线程启动?
- 如何在 c++ 中创建计时器
- C++回调计时器实现
- 在计时器或主线程外部的命令上销毁/替换线程
- 如何制作每秒从 30 乘 1 倒计时的计时器?
- 保留计时器集合(对象与指针)的最佳方法
- 在网络套接字计时器滴答后增加asio短读错误
- 是否可以仅使用标准 c++/c++11 实现不带"sleep"的计时器?
- 在没有NtSetTimerResolution的Windows上提高计时器分辨率(高分辨率)
- 计时器坏了或者其他什么的
- 功能计时器阻止主功能继续
- IO服务重新启动后,Boost最后期限计时器持续触发
- boost asio计时器是否会在"取消"时阻塞
- Poco 计时器,具有来自同一类的回调
- 使计时器在C++进程中的特定时间关闭,以便同步两个进程