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

asio::steady_timer配合use_awaitable跨协程修改时失效问题求助

问题分析与解决

你的代码存在两个关键问题导致Leave foo无法输出:

1. 阻塞调用占用IO线程

bar里的sleep(2)是同步阻塞调用,会直接卡住io_context运行的唯一线程,在这2秒内asio的事件循环完全无法处理任何异步操作,包括foo里的定时器等待逻辑。必须用asio的异步等待替代同步sleep。

2. 修改定时器过期时间未触发原有等待

当你调用timer.expires_after修改过期时间时,之前已经通过async_wait注册的等待操作不会自动被唤醒或取消。原有的co_await timer.async_wait会一直挂起,直到对应的等待操作被触发或取消。


修正后的代码

#include <asio.hpp>
#include <iostream>
#include <chrono>

using namespace std;
using namespace asio;
using namespace chrono_literals;

static awaitable<void> foo(steady_timer& timer)
{
    cout << "Enter foo" << endl;
    timer.expires_from_now(steady_timer::clock_type::duration::max());
    try
    {
        co_await timer.async_wait(use_awaitable);
    }
    catch (const system_error& e)
    {
        // 捕获预期的操作取消错误
        if (e.code() != error::operation_aborted)
            throw;
    }
    cout << "Leave foo" << endl;
}

static awaitable<void> bar(steady_timer& timer)
{
    cout << "Enter bar" << endl;
    // 用asio异步等待替代同步sleep,不阻塞IO线程
    co_await steady_timer(timer.get_executor(), 2s).async_wait(use_awaitable);
    // 修改定时器过期时间后,取消之前的单个等待操作
    timer.expires_after(1s);
    timer.cancel_one();
    cout << "Leave bar" << endl;
    co_return;
}

int main()
{
    io_context ioService;
    steady_timer timer(ioService);

    co_spawn(ioService, foo(timer), detached);
    co_spawn(ioService, bar(timer), detached);

    ioService.run();
    printf("The End\n");
    return 0;
}

关键修改说明

  • 替换sleep(2)为co_await steady_timer(...):让等待过程异步化,不会阻塞io_context的事件循环,保证foo的等待逻辑能被正常处理。
  • 添加timer.cancel_one():在修改定时器过期时间后,主动取消之前注册的单个等待操作,触发foo里的co_await恢复执行。此时async_wait会抛出error::operation_aborted错误,需捕获并处理(这是主动触发的预期流程)。
  • 增加异常捕获:处理操作取消的错误,避免程序崩溃。

运行修正后的代码,输出会变为:

Enter foo
Enter bar
Leave bar
Leave foo
The End

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:35:24