boost::deadline_timer编译报错WaitHandler类型要求不满足问题求助
问题核心原因
- 异步回调不支持直接传入未绑定实例的类成员函数指针:成员函数调用隐含
this指针参数,Boost.Asio无法直接识别该参数,导致编译校验不通过。 io_service使用逻辑错误:单独为定时器创建timer_io且在构造函数中同步调用run()会导致线程阻塞,后续异步等待操作根本无法提交到事件队列;同时没有持续运行的事件循环调度回调,所以即使换成静态函数也不会触发。
修复方案
第一步:头文件修改
删除冗余的独立io_service,增加生命周期安全保证,修改后cnx.h如下:
#ifndef CNX_H #define CNX_H #include <boost/asio.hpp> #include <memory> #include <iostream> using boost::asio::ip::tcp; typedef boost::asio::io_service ioservice; // 继承enable_shared_from_this保证回调触发前实例不会被销毁 class cnx : public std::enable_shared_from_this<cnx> { public: inline static int timeout_mili = 10000; using ptr = std::shared_ptr<cnx>; static ptr create(ioservice& io) { return std::make_shared<cnx>(io); } cnx(ioservice& io); void timer_counter_reset(); bool conectado; tcp::socket& get_socket() { return s; } // 对外暴露socket供连接/读写逻辑使用 private: tcp::socket s; boost::asio::deadline_timer cnx_timer; void timer_ended(const boost::system::error_code& e); }; #endif // CNX_H
第二步:实现文件修改
用std::bind绑定实例到成员函数回调,定时器和socket共用同一个外部传入的io_service,移除构造函数中的阻塞run()调用,修改后cnx.cpp如下:
#include "cnx.h" cnx::cnx(ioservice& io) : s(io), conectado(false), cnx_timer(io, boost::posix_time::milliseconds(cnx::timeout_mili)) { // 绑定成员函数+当前实例,占位符对应回调的error_code参数 cnx_timer.async_wait(std::bind(&cnx::timer_ended, shared_from_this(), std::placeholders::_1)); } void cnx::timer_counter_reset() { boost::system::error_code ec; cnx_timer.cancel(ec); // 取消之前的定时任务 if (ec) return; // 重置超时时间 cnx_timer.expires_from_now(boost::posix_time::milliseconds(timeout_mili), ec); if (ec) return; // 重新提交异步等待 cnx_timer.async_wait(std::bind(&cnx::timer_ended, shared_from_this(), std::placeholders::_1)); } void cnx::timer_ended(const boost::system::error_code& e) { // 只有cancel触发的operation_aborted是正常重置,其余情况判定为超时 if(e == boost::asio::error::operation_aborted){ std::cout << "cnx resetted timer" << std::endl; return; } this->conectado = false; // 可补充s.close()逻辑主动关闭超时连接 }
第三步:外部事件循环统一调度
你需要在程序入口统一启动io_service的事件循环,所有异步操作的回调都会在此处触发,示例:
int main() { ioservice io; auto conn = cnx::create(io); // 此处补充你的socket连接、读数据逻辑,收到客户端数据时调用conn->timer_counter_reset()重置超时 io.run(); // 持续运行事件循环,不要提前退出 return 0; }
内容的提问来源于stack exchange,提问作者Fnr
相关产品推荐
相关产品推荐

