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
相关产品推荐
相关产品推荐

