如何在组合函数中使用boost::asio::defer()?Boost 1.66用法疑问
关于Boost.Asio中
defer替代asio_handler_is_continuation的正确用法 嘿,我来帮你理清这个问题~从Boost 1.66开始弃用asio_handler_is_continuation钩子,转而用defer,本质是把原来隐式的钩子判断改成了显式调用,逻辑其实更清晰。
核心逻辑对应
原来你通过重载asio_handler_is_continuation并返回true,是在告诉Asio:“这个handler是前一个异步操作的延续,不需要额外调度,直接在当前完成处理的线程里执行就行”。而defer就是干这个事的——当你用defer提交任务时,Asio的行为就和钩子返回true时的post完全一致。
具体用法示例(结合async_read_until场景)
假设之前你用钩子的写法是这样的:
// 旧写法:依赖asio_handler_is_continuation钩子 void on_read_complete(const boost::system::error_code& ec, std::size_t bytes_read) { if (!ec) { // 先处理读取到的数据... // 发起下一次读取,希望作为延续操作执行 boost::asio::async_read_until(m_stream, m_buffer, '\n', std::bind(&MyClass::on_next_read, this, std::placeholders::_1, std::placeholders::_2)); } } // 重载钩子函数,标记我们的handler为延续 template <typename Handler> bool asio_handler_is_continuation(Handler* handler) { // 这里需要判断handler是否是我们的目标handler,返回true return /* 你的判断逻辑 */; }
现在改成defer的写法,直接显式声明延续操作:
// 新写法:用defer替代钩子 void on_read_complete(const boost::system::error_code& ec, std::size_t bytes_read) { if (!ec) { // 先处理读取到的数据... // 用defer提交下一次读取的发起操作,Asio会直接在当前线程执行 boost::asio::defer(m_stream.get_executor(), [this]() { boost::asio::async_read_until(m_stream, m_buffer, '\n', [this](const boost::system::error_code& ec2, std::size_t bytes2) { on_next_read(ec2, bytes2); }); }); } }
关键区别和注意点
- 显式 vs 隐式:原来的钩子是全局重载,需要识别特定的Handler类型,很容易出错;
defer是在需要的地方直接调用,语义更明确,可读性更强。 - 执行时机:
defer提交的任务会被放到当前调用链的末尾执行,不会触发额外的线程切换,和钩子返回true时的post行为完全一致。 - 适用场景:当你在一个异步操作的完成handler里,紧接着发起另一个相关的异步操作,并且希望避免不必要的线程调度开销时,就用
defer。
内容的提问来源于stack exchange,提问作者he rambled
相关产品推荐
相关产品推荐

