You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

boost::deadline_timer编译报错WaitHandler类型要求不满足问题求助

问题核心原因

  1. 异步回调不支持直接传入未绑定实例的类成员函数指针:成员函数调用隐含this指针参数,Boost.Asio无法直接识别该参数,导致编译校验不通过。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 02:54:04