【问题标题】:C++ Boost ASIO simple periodic timer?C++ Boost ASIO 简单的周期性定时器?
【发布时间】:2011-05-15 03:08:12
【问题描述】:

我想要一个非常简单的周期性计时器来每 50 毫秒调用一次我的代码。我可以制作一个一直休眠 50 毫秒的线程(但这很痛苦)...我可以开始研究用于制作计时器的 Linux API(但它不是可移植的)...

我希望喜欢使用 boost.. 我只是不确定这是否可能。 boost 是否提供此功能?

【问题讨论】:

    标签: c++ linux boost boost-asio


    【解决方案1】:

    一个非常简单但功能齐全的示例:

    #include <iostream>
    #include <boost/asio.hpp>
    
    boost::asio::io_service io_service;
    boost::posix_time::seconds interval(1);  // 1 second
    boost::asio::deadline_timer timer(io_service, interval);
    
    void tick(const boost::system::error_code& /*e*/) {
    
        std::cout << "tick" << std::endl;
    
        // Reschedule the timer for 1 second in the future:
        timer.expires_at(timer.expires_at() + interval);
        // Posts the timer event
        timer.async_wait(tick);
    }
    
    int main(void) {
    
        // Schedule the timer for the first time:
        timer.async_wait(tick);
        // Enter IO loop. The timer will fire for the first time 1 second from now:
        io_service.run();
        return 0;
    }
    

    请注意,调用expires_at() 设置新的到期时间非常重要,否则计时器将立即触发,因为它的当前到期时间已经到期。

    【讨论】:

    • @AndrewStone 我不这么认为,但如果你担心的话,你可以使用一个稳定的计时器来代替,它不会受到系统时间变化的影响。看看这里:boost.org/doc/libs/1_65_1/doc/html/boost_asio/reference/… 应该很容易移植我上面的例子来使用它。
    • 请注意,boost::asio::io_service::run() 会阻塞线程执行,因此您无法在调用它后执行指令并期望计时器也同时触发。
    • 为什么允许在没有'()'的情况下调用tick,即不应该是 timer.async_wait(tick());
    • @jaxkewl 原因是tick 没有被立即调用。相反,它的引用被传递给async_wait(),它最终会在未来调用它。
    • +1。 expires_at 比官方示例使用的expires_after 准确得多。 expires_after 在定时器周期中引入了偏差,在高速率下实际上变得无用。
    【解决方案2】:

    Boosts Asio 教程的第二个例子解释了它。
    你可以找到它here

    之后,check the 3rd example 看看如何以周期性的时间间隔再次调用它

    【讨论】:

    • @PhilippLudwig 感谢您的通知。他们似乎改变了链接格式。我更新了链接
    • 请注意,boost::asio::io_service::run() 会阻塞线程执行,因此您无法在调用它后执行指令并期望计时器也同时触发。
    • 等等,如果 IO.run 阻塞线程执行,那么异步的意义何在?
    【解决方案3】:

    进一步扩展这个简单的例子。它会像 cmets 中所说的那样阻塞执行,所以如果你想运行更多的 io_services,你应该像这样在一个线程中运行它们......

    boost::asio::io_service io_service;
    boost::asio::io_service service2;
    timer.async_wait(tick);
    boost::thread_group threads;
    threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
    service2.run();
    threads.join_all();
    

    【讨论】:

      【解决方案4】:

      由于我之前的答案有一些问题,这里是我的例子:

      #include <boost/asio.hpp>
      #include <boost/bind.hpp>
      #include <boost/date_time/posix_time/posix_time.hpp>
      #include <iostream>
      
      void print(const boost::system::error_code&, boost::asio::deadline_timer* t,int* count)
      {
          if (*count < 5)
          {
              std::cout << *count << std::endl;
              ++(*count);
              t->expires_from_now(boost::posix_time::seconds(1));
              t->async_wait(boost::bind(print, boost::asio::placeholders::error, t, count));
          }
      }
      
      int main()
      { 
          boost::asio::io_service io;
          int count = 0;
          boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
      
          t.async_wait(boost::bind(print, boost::asio::placeholders::error, &t, &count));
      
          io.run();
          std::cout << "Final count is " << count << std::endl;
      
          return 0;
      
      }
      

      它做了它应该做的事:数到五。希望对某人有所帮助。

      【讨论】:

        【解决方案5】:

        封装此功能的 Boost Asio 附加类(每 N 毫秒调用一次指定函数):https://github.com/mikehaben69/boost/tree/main/asio

        repo 包含一个演示源文件和 makefile。

        【讨论】:

          猜你喜欢
          • 2011-12-17
          • 1970-01-01
          • 1970-01-01
          • 2019-11-30
          • 2014-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多