2011-03-21 91 views
3

我試過在這個簡單的測試應用程序中使用boost deadline_timer,但遇到了一些麻煩。目標是定時器使用deadline_timerexpires_at()成員函數每45毫秒觸發一次。 (我需要一個絕對的時間,所以我不考慮expires_from_now()。我現在也不關心漂移)。當我運行該程序時,wait()不會等待45毫秒!然而,沒有錯誤報道。我以某種方式錯誤地使用圖書館?boost deadline_timer不等待

樣例程序:

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/bind.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <iostream> 
using namespace std; 

int main() 
{ 
     boost::asio::io_service Service; 
     boost::shared_ptr<boost::thread> Thread; 
     boost::asio::io_service::work RunForever(Service); 
     Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service))); 
     boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service)); 

     while(1) 
     { 
       boost::posix_time::time_duration Duration; 
       Duration = boost::posix_time::microseconds(45000); 
       boost::posix_time::ptime Start = boost::posix_time::microsec_clock::local_time(); 
       boost::posix_time::ptime Deadline = Start + Duration; 
       boost::system::error_code Error; 
       size_t Result = Timer->expires_at(Deadline, Error); 
       cout << Result << ' ' << Error << ' '; 
       Timer->wait(Error); 
       cout << Error << ' '; 
       boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time(); 
       (cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush(); 
     } 
     return 0; 
} 

回答

6

您正在混合當地時間與系統時間。 asio比較你的本地時間的時間很可能是你希望截止日期設置的時間之後的幾個小時,所以等待立即返回(取決於你住的地方;同樣的代碼也可能等待幾個小時)。爲了避免這種混淆,絕對時間應該來自asio :: time_traits。

#include <boost/asio.hpp> 
#include <boost/asio/time_traits.hpp> 
#include <boost/thread.hpp> 
#include <boost/bind.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <iostream> 
using namespace std; 

typedef boost::asio::time_traits<boost::posix_time::ptime> time_traits_t; 
int main() {   
    boost::asio::io_service Service;   
    boost::shared_ptr<boost::thread> Thread;   
    boost::asio::io_service::work RunForever(Service);   
    Thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &Service))); 
    boost::shared_ptr<boost::asio::deadline_timer> Timer(new boost::asio::deadline_timer(Service));   
    while(1)   
    {     
     boost::posix_time::time_duration Duration; 
     Duration = boost::posix_time::microseconds(45000); 
     boost::posix_time::ptime Start = time_traits_t::now(); 
     boost::posix_time::ptime Deadline = Start + Duration; 
     boost::system::error_code Error; 
     size_t Result = Timer->expires_at(Deadline, Error); 
     cout << Result << ' ' << Error << ' '; 
     Timer->wait(Error); 
     cout << Error << ' '; 
     boost::posix_time::ptime End = boost::posix_time::microsec_clock::local_time(); 
     (cout << "Duration = " << (End - Start).total_milliseconds() << " milliseconds" << endl).flush(); 
    }   
    return 0; 
} 

在這種情況下應該適合您。

4

你混合異步方法io_service::run與同步方法deadline_timer::wait。這不起作用。請使用deadline_timer::async_waitio_service::run,或跳過io_service::run,只使用deadline_timer::wait。你也不需要一個線程來調用io_service:run如果你走異步路由,一個線程就可以做得很好。這兩個概念在Asio tutorial基本技能部分中有詳細說明。

void print(const boost::system::error_code& /*e*/) 
{ 
    std::cout << "Hello, world!\n"; 
} 

int main() 
{ 
    boost::asio::io_service io; 

    boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); 
    t.async_wait(print); 
    io.run(); 

    return 0; 
} 

注意,你需要給一些工作你io_service之前調用run()的服務。在這個例子中,async_wait就是這樣的工作。

潛在無關:45ms是一個相當小的三角洲。根據我的經驗,任何處理器通過Asio epoll反應堆隊列所需的最短時間大約爲30毫秒,在較高負載情況下,這可能會相當長。雖然這在很大程度上取決於您的應用程序