2012-04-15 22 views
6

Khi bạn gọi expires_from_now() trên bộ hẹn giờ đang chạy, bộ hẹn giờ bị hủy và bộ hẹn giờ mới được gọi. Vì vậy, trình xử lý liên quan được gọi. Dễ phân biệt đối xử trong bộ xử lý giữa bộ hẹn giờ đã hủy và hết hạn. Tuy nhiên, tôi tự hỏi, nếu có một cách để phân biệt đối xử giữa một bộ đếm thời gian đã hết hạn và được truy xuất lại. Trong cả hai trường hợp, trình xử lý được gọi là với error_code operation_aborted. Hoặc có thể tôi thiếu một số chi tiết.Làm thế nào để bạn phân biệt đối xử bị hủy khỏi deadline_timer tăng

Đoạn code dưới đây tạo ra kết quả như sau:

20120415 21:32:28079507 Main: Timer1 set to 15 s.  
20120415 21:32:28079798 Main: Timer1 set to 12 s.  
20120415 21:32:28079916 Handler1: Timer 1 was cancelled or retriggered.  
20120415 21:32:40079860 Handler1: expired. 

Điều này cho thấy rằng xử lý là không thể thực hiện hành động cho một handler hủy bỏ, vì retriggering một bộ đếm thời gian sẽ gọi xử lý tương tự và do đó thực hiện tương tự hành động. Đó có lẽ không phải là hành vi dự định.

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/date_time/posix_time/posix_time_io.hpp> 
#include <iostream> 

using namespace boost::posix_time; 
using namespace std; 

void handler1(const boost::system::error_code &ec) 
{ 
    if (ec == boost::asio::error::operation_aborted) 
    { 
     cout << microsec_clock::local_time() << " Handler1: Timer was cancelled or retriggered." << endl; 
    } 
    else 
    { 
     cout << microsec_clock::local_time() << " Handler1: Timer expired." << endl; 
    } 
} 

boost::asio::io_service io_service1; 

void run1() 
{ 
    io_service1.run(); 
} 

int main() 
{ 
    time_facet *facet = new time_facet("%Y%m%d %H:%M:%S%f"); 
    cout.imbue(locale(cout.getloc(), facet)); 

    boost::asio::deadline_timer timer1(io_service1, seconds(15)); 
    timer1.async_wait(handler1); 
    cout << microsec_clock::local_time() << " Main: Timer1 set to 15 s." << endl; 
    // now actually run the timer 
    boost::thread thread1(run1); 
    timer1.expires_from_now(seconds(12)); 
    cout << microsec_clock::local_time() << " Main: Timer1 set to 12 s." << endl; 
    // here the timer is running, but we need to reset the deadline 
    timer1.async_wait(handler1); 
    thread1.join(); // wait for thread1 to terminate 
} 
+1

Xin vui lòng, cho chúng tôi biết những gì bạn muốn đạt được. Bức tranh lớn hơn là gì? –

+0

Tôi đang cố gắng triển khai một số trì hoãn bật do sự kiện kích hoạt. Tôi có thể thực hiện độ trễ bật lên cơ bản mà không cần kích hoạt lại. Nhưng nếu bạn chấp nhận biến hoặc thay đổi thời gian trì hoãn, tôi sẽ phải thu hồi nó. –

+0

Và tại sao không làm gì cả, khi bạn nhận được operation_aborted, hãy nhớ một handler cho trước và thiết lập lại nó? –

Trả lời

4

Tôi khuyên bạn nên tạo lớp để bao bọc một deadline_timer bằng cách sử dụng bố cục. Khi hủy, hãy đặt cờ để nhớ rằng nó đã bị hủy. Trong trình xử lý, hãy đặt lại cờ. Khi gọi expires_from_now() không đặt cờ.

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/date_time/posix_time/posix_time_io.hpp> 
#include <iostream> 

class Timer 
{ 
public: 
    Timer(
      const std::string& name, 
      boost::asio::io_service& io_service 
     ) : 
     _name(name), 
     _timer(io_service), 
     _cancelled(false) 
    { 
     _timer.expires_from_now(boost::posix_time::seconds(0)); 
     this->wait(); 
    } 

    void wait() 
    { 
     _timer.async_wait(
       boost::bind(
        &Timer::handler, 
        this, 
        boost::asio::placeholders::error 
        ) 
       ); 
    } 

    void cancel() { 
     _cancelled = true; 
     _timer.cancel(); 
    } 

    void restart() { 
     _timer.expires_from_now(boost::posix_time::seconds(5)); 
    } 

private: 
    void handler(
      const boost::system::error_code& error 
      ) 
    { 
     if (!error) { 
      std::cout << _name << " " << __FUNCTION__ << std::endl; 
      _timer.expires_from_now(boost::posix_time::seconds(5)); 
      this->wait(); 
     } else if (error == boost::asio::error::operation_aborted && _cancelled) { 
      _cancelled = false; 
      std::cout << _name << " " << __FUNCTION__ << " cancelled" << std::endl; 
     } else if (error == boost::asio::error::operation_aborted) { 
      std::cout << _name << " " << __FUNCTION__ << " retriggered" << std::endl; 
      this->wait(); 
     } else { 
      std::cout << "other error: " << boost::system::system_error(error).what() << std::endl; 
     } 
    } 

private: 
    const std::string _name; 
    boost::asio::deadline_timer _timer; 
    bool _cancelled; 
}; 

int 
main() 
{ 
    boost::asio::io_service ios; 
    Timer timer1("timer1", ios); 
    Timer timer2("timer2", ios); 

    boost::thread thread(
      boost::bind(
       &boost::asio::io_service::run, 
       boost::ref(ios) 
       ) 
      ); 

    sleep(3); 
    std::cout << "cancelling" << std::endl; 
    timer1.cancel(); 
    timer2.restart(); 

    thread.join(); 
} 

phiên mẫu

macmini:stackoverflow samm$ ./a.out 
timer1 handler 
timer2 handler 
cancelling 
timer1 handler cancelled 
timer2 handler retriggered 
timer2 handler 
^C 
macmini:stackoverflow samm$ 
0

Tôi không biết cách nào và có lẽ không có cách nào tốt để làm điều đó (không có gì trong tài liệu nói rằng bạn có thể phân biệt hai tình huống này).

Tôi tin rằng điều này đã được thực hiện theo mục đích. Thiết deadline_timer để một thời gian hết hạn mới, cancells bất kỳ xử lý trước, bởi vì:

  • đôi khi rất khó để nói nếu một cái gì đó đã được chờ đợi trên thời gian, do đó nó sẽ được khó có thể nói chính xác những gì sẽ xảy ra, khi bạn đặt thời gian hết hạn;
  • đây là một cách dễ dàng để ngăn các sự kiện bị hủy kích hoạt chạy hai lần, yêu cầu xử lý mã lỗi khác một cách đặc biệt dễ bị lỗi hơn.
Các vấn đề liên quan