提升线程和计时器,C ++

时间:2009-08-27 15:35:41

标签: c++ multithreading boost timer boost-asio

我有自定义类'sau_timer'的代码:

sau_timer::sau_timer(int secs, timerparam f, vector<string> params) : strnd(io), 
    t(io, boost::posix_time::seconds(secs))
{
    assert(secs > 0);
    this->f = f;
    this->params = params;
    t.async_wait(strnd.wrap(boost::bind(&sau_timer::exec, this, _1)));
    boost::thread thrd(boost::bind(&boost::asio::io_service::run, &io));
    io.run();
}

void sau_timer::exec(const boost::system::error_code&) {
    (f)(params);
}

我想要它,以便当我制作一个sau_timer对象时,计时器将启动,但允许程序继续执行。例如,这是main():

int main(int argc, char* argv[])
{
    vector<string> args(1);
    args[0] = "Hello!";
    sau_timer timer_test(3, sau_prompt, args);
    args[0] = "First!";
    sau_prompt(args);
    timer_test.thrd.join();
    return 0;
}

我的目的是生成timer_test,启动一个在调用sau_prompt(“Hello!”)之前等待三秒的计时器,但是首先调用sau_prompt(“First!”)。此时,Hello显示在First之前的提示中,表示计时器正在暂停整个程序三秒钟,然后才允许它继续。我希望计时器在后台运行。

我做错了什么?代码编译......

谢谢。

2 个答案:

答案 0 :(得分:6)

你在sau_timer中调用“io.run()” - 这实际上告诉asio reactor如果可以的话处理任何/所有挂起的异步事件。

您应该在设置事件后调用run或post,这是正常情况。查看asio文档中的示例。

#include <iostream>
#include <asio.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time.hpp>
#include <boost/thread.hpp>


class event_timer
{
public:

   event_timer(asio::io_service& io_service,
               const std::size_t& tid,
               const std::size_t& interval = 5)
   : io_service_(io_service),
     timer_(io_service),
     tid_(tid),
     interval_(interval),
     tick_count_(0),
     total_diff_(0)
   {
   }

   void start()
   {
      timer_.cancel();
      initiate_timer();
   }

   void stop()
   {
      timer_.cancel();
   }

   void set_interval(const std::size_t& milliseconds)
   {
      interval_ = milliseconds;
   }

private:

   inline void initiate_timer()
   {
      if (interval_)
      {
         timer_.expires_from_now(boost::posix_time::milliseconds(interval_));
         timer_.async_wait(
            boost::bind(&event_timer::handle_timer_event,this,
               asio::placeholders::error));
         before_ = boost::posix_time::microsec_clock::universal_time();
      }
   }

   inline void handle_timer_event(const asio::error_code& error)
   {
      if (!error && interval_)
      {
         after_ = boost::posix_time::microsec_clock::universal_time();
         boost::posix_time::time_duration duration = after_ - before_;
         total_diff_ += std::abs(interval_ - duration.total_milliseconds());
         ++tick_count_;
         if (tick_count_ < 200)
            initiate_timer();
         else
            std::cout << "Timer["<< tid_ <<"]\tTick["<< tick_count_ <<"] Average Diff: " << total_diff_ / (1.0 * tick_count_) << std::endl;
      }
   }

   asio::io_service& io_service_;
   std::size_t tid_;
   std::size_t interval_;
   std::size_t tick_count_;
   asio::deadline_timer timer_;
   boost::posix_time::ptime before_;
   boost::posix_time::ptime after_;
   std::size_t total_diff_;
};

int main()
{

   std::cout << "Timer Test" << std::endl;

   asio::io_service io_service;

   try
   {
      const std::size_t et_cnt = 1000;
      std::vector<event_timer*> et_lst;

      for(unsigned int i = 0; i < et_cnt; ++i)
      {
         et_lst.push_back(new event_timer(io_service,i,10));
      }

      for(unsigned int i = 0; i < et_cnt;)
      {
         et_lst[i++]->start();
      }

      std::size_t thread_pool_size = 100;

      //Create a pool of threads to run all of the io_services.
      std::vector<boost::shared_ptr<boost::thread> > threads;
      for (std::size_t i = 0; i < thread_pool_size; ++i)
      {
         boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&asio::io_service::run, &io_service)));
         threads.push_back(thread);
      }

      // Wait for all threads in the pool to exit.
      for (std::size_t i = 0; i < threads.size(); ++i)
         threads[i]->join();
      for(unsigned int i = 0; i < et_cnt; delete et_lst[i++]);

   }
   catch(std::exception& e)
   {
      std::cout << "Exception: " << e.what() << std::endl;
      return 1;
   }

   return 0;
}

答案 1 :(得分:0)

考虑名称空间和boost版本1.69,应进行三处修改:

  1. #include <asio.hpp>更改为#include <boost/asio.hpp>
  2. 添加:using namespace boost; using namespace boost:asio;
  3. inline void handle_timer_event(const asio::error_code& error)更改为void handle_timer_event(const boost::system::error_code& error)