Boost asio 截止时间计时器立即完成(C++)

Posted

技术标签:

【中文标题】Boost asio 截止时间计时器立即完成(C++)【英文标题】:Boost asio deadline timer completing immediately (C++) 【发布时间】:2021-03-04 10:47:26 【问题描述】:

下面的代码会立即打印“已连接”到控制台,而不是 10 秒后。为什么是这样?这与我传递print 回调的方式有关吗?

void print(const boost::system::error_code& e) 
  std::cout << "connected!" << std::endl;


class WebSocketSession 
 public:
  WebSocketSession(asio::io_context &io_context) : io_context_(io_context) 
  void connect() 
    boost::asio::deadline_timer
        timer(io_context_, boost::posix_time::seconds(10));
    timer.async_wait(&print);
  
 private:
  asio::io_context &io_context_;
;

class WebSocketClient 
 public:
  WebSocketClient(asio::io_context &io_context) : io_context_(io_context) 
  std::unique_ptr<WebSocketSession> exec() 
    auto session = std::make_unique<WebSocketSession>(io_context_);
    session->connect();
    return session;
  
 private:
  asio::io_context &io_context_;
;

int main() 
  asio::io_context io_context;
  WebSocketClient clientio_context;
  std::unique_ptr<WebSocketSession> session = client.exec();
  io_context.run();
  return 0;

【问题讨论】:

deadline_timer 不能是局部变量,因为async_wait 立即返回,所以定时器在函数作用域结束时被销毁。 谢谢,这很有道理。我还是不明白为什么在销毁定时器的情况下调用回调? 回调被调用来通知你发生了一些错误。查看deadline_timer dtor的参考。 啊,我明白了。非常感谢您的帮助 【参考方案1】:

如 cmets 中所述,deadline_timer 被过早销毁,因为它是一个局部变量,从而取消了 I/O 操作。

如果我们添加一些错误处理,我们将看到实际报告的错误:

void print(const boost::system::error_code& e) 
    if (e.failed())
        std::cout << "error: " << e.message() << std::endl;
    else
        std::cout << "connected!" << std::endl;

打印:

error: The I/O operation has been aborted because of either a thread exit or an application request

一个可能的解决方法是将deadline_timer 移动为WebSocketSession 的成员:

class WebSocketSession 
public:
    WebSocketSession(boost::asio::io_context& io_context) : io_context_(io_context),
        timer_(io_context, boost::posix_time::seconds(10)) 
    void connect() 
        timer_.async_wait(&print);
    
private:
    boost::asio::io_context& io_context_;
    boost::asio::deadline_timer timer_;
;

【讨论】:

以上是关于Boost asio 截止时间计时器立即完成(C++)的主要内容,如果未能解决你的问题,请参考以下文章

截止日期计时器到期,现在怎么办?

提升 asio 行为 - 从多个线程调用 ios_service::run

boost :: asio :: steady_timer在boost :: dll中不起作用

C++ Boost ASIO 简单的周期性定时器?

boost::asio::io_service类

在 boost::asio::io_service 上调用 run 时崩溃