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

协程技术:如何在非协程感知库代码中调用async_*函数

解决方案:不修改接口前提下在底层函数中使用Asio协程

由于RequestContext的doSomething()是普通虚函数,无法直接改为协程函数,我们可以通过以下几种方案在不修改接口的前提下,在具体实现中使用co_await和异步操作:

方案一:启动独立协程执行异步逻辑(无需上层等待)

直接在doSomething()内部用boost::asio::co_spawn启动独立协程,异步操作会在后台由io_context调度执行,上层协程无需等待即可继续运行。适合不需要同步感知异步操作完成的场景。

修改后的AsyncRequestContext实现:

struct AsyncRequestContext : public RequestContext
{
    boost::asio::io_context ioc;

    void doSomething() override
    {
        // 启动独立协程执行异步逻辑
        boost::asio::co_spawn(ioc, [this]() -> boost::asio::awaitable<void> {
            boost::asio::deadline_timer timer(ioc);
            timer.expires_from_now(boost::posix_time::seconds(5));
            co_await timer.async_wait(boost::asio::use_awaitable);
            // 可继续添加其他co_await异步操作
            std::cout << "异步操作完成\n";
        }, boost::asio::detached);
    }
};

方案二:让上层协程等待异步操作完成

如果需要上层协程等待doSomething()内的异步操作完成后再继续执行,可以在具体实现类中保存一个awaitable任务,在上层协程中通过co_await等待该任务完成。这种方式保持了协程的同步语义,符合Asio协程的设计风格。

修改后的代码:

struct AsyncRequestContext : public RequestContext
{
    boost::asio::io_context ioc;
    // 保存待执行的异步任务
    boost::asio::awaitable<void> pending_task_;

    void doSomething() override
    {
        // 将异步逻辑包装为awaitable任务
        pending_task_ = [this]() -> boost::asio::awaitable<void> {
            boost::asio::deadline_timer timer(ioc);
            timer.expires_from_now(boost::posix_time::seconds(5));
            co_await timer.async_wait(boost::asio::use_awaitable);
            std::cout << "异步操作完成\n";
        }();
    }
};

// main中的协程修改为:
boost::asio::co_spawn(
    rctx.ioc,
    [&rctx]() -> boost::asio::awaitable<void> {
        middle(rctx);
        // 等待doSomething中启动的异步任务完成
        co_await rctx.pending_task_;
        co_return;
    },
    boost::asio::detached);

方案三:手动挂起/恢复上层协程(不推荐常规使用)

通过捕获上层协程的句柄,在doSomething()中手动挂起协程,待异步操作完成后恢复。这种方式无需上层协程额外等待,但需要手动管理协程生命周期,存在空指针、重复挂起/恢复等风险,仅在特殊场景下使用。

修改后的代码:

struct AsyncRequestContext : public RequestContext
{
    boost::asio::io_context ioc;
    // 保存当前调用的协程句柄
    boost::asio::coroutine_handle<> current_coro_;

    void doSomething() override
    {
        boost::asio::deadline_timer timer(ioc);
        timer.expires_from_now(boost::posix_time::seconds(5));
        // 异步回调中恢复协程
        timer.async_wait([this](const boost::system::error_code& ec) {
            if (!ec && current_coro_) {
                current_coro_.resume();
            }
        });
        // 挂起当前协程,等待异步操作完成
        current_coro_.suspend();
        // 协程恢复后继续执行后续逻辑
        std::cout << "异步操作完成\n";
    }
};

// main中的协程修改为:
boost::asio::co_spawn(
    rctx.ioc,
    [&rctx]() -> boost::asio::awaitable<void> {
        // 获取当前协程句柄并保存到上下文
        rctx.current_coro_ = co_await boost::asio::this_coro::coroutine;
        middle(rctx);
        co_return;
    },
    boost::asio::detached);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:18:14