2009-08-27 95 views
0

我有一個自定義類「sau_timer」這樣的代碼:加速線程和定時器,C++

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對象,定時器將啓動,但允許程序執行繼續。例如,這是主要的():

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之前等待三秒計時器,但sau_prompt((「你好!」)「第一!」 )將首先被調用。目前,Hello在第一次提示之前顯示,表明計時器正在暫停整個程序三秒鐘,然後才允許繼續。我想讓計時器在後臺運行。

我在做什麼錯?代碼彙編...

謝謝。

回答

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; 
} 
+0

我把\t timer_test.io.run();在行sau_timer timer_test(3,sau_prompt,args)下面;在main()中,並從類構造函數中移除了io.run(),但效果仍然相同。我擔心我誤解了? – Xenoprimate 2009-08-27 16:23:43

+7

示例代碼應該足以讓您瞭解如何使用asio。您看到這個想法並不是創建線程來運行,而是將對象稱爲計時器或接收器對象,而是創建運行io_services的多個線程,並讓這些線程io_services以線程/併發方式運行異步調用。 – 2009-08-28 19:20:08