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

Boost Asio:如何实现从yield返回后自动执行回调?

Boost Asio实现yield返回后自动执行回调的方案

Boost Asio原生的yield_context本身不直接支持自动执行回调的功能,但可以通过自定义包装yield上下文的方式实现需求,无需在每个异步操作后显式调用回调。

核心思路

封装原生yield_context,重载其operator()来捕获异步操作的完成时机,在调用原始yield的处理逻辑后自动插入自定义回调。

实现代码示例

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <functional>
#include <iostream>

// 自定义带自动回调的yield上下文包装类
class YieldWithAutoCallback {
public:
    YieldWithAutoCallback(boost::asio::yield_context yield, std::function<void()> callback)
        : yield_(std::move(yield)), auto_callback_(std::move(callback)) {}

    // 重载operator(),适配异步操作的handler签名
    template <typename CompletionToken>
    auto operator()(CompletionToken&& token) {
        return boost::asio::bind_executor(
            yield_.get_executor(),
            [this, token = std::forward<CompletionToken>(token)](auto&&... args) mutable {
                // 先执行原生yield的回调逻辑,恢复协程
                std::invoke(token, std::forward<decltype(args)>(args)...);
                // 自动执行自定义回调
                if (auto_callback_) {
                    auto_callback_();
                }
            }
        );
    }

    // 暴露原生yield的executor,满足Asio接口要求
    auto get_executor() const noexcept {
        return yield_.get_executor();
    }

private:
    boost::asio::yield_context yield_;
    std::function<void()> auto_callback_;
};

使用方式

在协程中创建自定义的yield上下文,替代原生yield即可:

void https_client(boost::asio::io_context& io_context, boost::asio::ssl::context& ssl_context) {
    boost::asio::spawn(io_context, [&](boost::asio::yield_context yield) {
        // 定义要自动执行的基础回调
        auto base_callback = []() {
            std::cout << "异步操作完成,自动执行基础回调" << std::endl;
        };

        // 创建带自动回调的yield上下文
        YieldWithAutoCallback yield_with_cb(yield, base_callback);

        // 后续所有使用该上下文的异步操作,完成后都会自动触发回调
        boost::asio::ssl::stream<boost::asio::ip::tcp::socket> stream(io_context, ssl_context);
        // 省略握手、连接等前置步骤...

        http::request<http::string_body> req(http::verb::get, "/", 11);
        req.set(http::field::host, "example.com");
        req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

        // 执行async_write,完成后自动触发base_callback
        http::async_write(stream, req, yield_with_cb);

        http::response<http::dynamic_body> res;
        boost::beast::flat_buffer buffer;
        // 执行async_read,完成后同样自动触发base_callback
        http::async_read(stream, buffer, res, yield_with_cb);
    });
}

注意事项

  • 回调会在异步操作完成、协程恢复后执行,不会干扰异步操作的结果处理逻辑;
  • 如果回调需要访问协程内的局部变量,需注意变量生命周期,避免悬空引用;
  • 可根据需求扩展包装类,比如支持携带异步操作的错误码、结果等参数的回调。

内容的提问来源于stack exchange,提问作者Zohar81

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:58:16