IO服务重启后,Boost截止时间计时器会连续触发

我正在处理一些通讯代码,因此需要一个定期的计时器进行监视。我在通讯中使用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次,然后haywire声称经过了数百秒。

我可以通过创建全新的IO服务和计时器来使此代码正常工作,但是鉴于它们应该可重用,这似乎是不必要的。

如果有人可以告诉我这里发生了什么,或者至少重现了我的结果,我将不胜感激。

abcdefgxxoo 回答:IO服务重启后,Boost截止时间计时器会连续触发

感谢@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,&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;
}
本文链接:https://www.f2er.com/3169933.html

大家都在问