如何取消Asio中的组合异步操作(含内置asio::async_connect及自定义操作)
Asio组合异步操作取消方案解答
1. 取消asio::async_connect操作
- 如果你使用 Boost 1.77+ / 独立Asio 1.19+ 版本,直接用Asio原生的取消机制即可:给
asio::async_connect传递绑定了取消槽的完成令牌,示例逻辑如下:
内置的asio::cancellation_signal cancel_sig; // 绑定取消槽到async_connect的完成令牌 asio::async_connect(sock, endpoints, asio::bind_cancellation_slot(cancel_sig.slot(), [](boost::system::error_code ec, asio::ip::tcp::endpoint ep) { // 处理完成逻辑,取消时ec为asio::error::operation_aborted })); // 需要取消时调用 cancel_sig.emit(asio::cancellation_type::all);asio::async_connect会自动在每个子basic_socket::async_connect操作完成后检查取消状态,若已触发取消会直接终止整个组合操作,不会继续执行后续排队的连接尝试,不需要手动调用socket的cancel方法。 - 如果你使用更旧的Asio版本,可以自行封装连接遍历逻辑,每次单个连接尝试完成后先检查自定义的取消标志,若标志已置位则直接返回
operation_aborted错误,不再发起下一个连接。
2. 通用场景下取消Asio内置组合异步操作
- 新版本Asio的原生取消机制已经完全解决了Robert Leahy 2019年演讲中提到的组合操作取消痛点,不需要重写任何内置组合操作:所有官方提供的组合操作(包括
async_read、async_write、async_read_until等)都已经默认适配了取消逻辑,只要给操作绑定cancellation_slot,触发取消信号后就会自动在子操作间隙终止整个组合任务,适配成本为0。 - 可以通过指定
cancellation_type控制取消粒度:比如cancellation_type::terminal直接终止所有操作,cancellation_type::partial仅终止当前运行的子操作,根据业务需求选择即可。 - 必须兼容旧版本Asio时,可以实现一个通用的流包装类,hook所有底层异步IO操作的发起入口,每次调用前检查全局的取消标志,这个包装类可以复用给所有组合操作,不需要挨个重写上层组合函数,成本远低于逐个重写组合操作。
3. 取消自定义的组合异步操作
- 如果你基于
asio::async_compose实现自定义组合操作,不需要自己实现整套取消令牌系统,直接适配Asio原生的取消机制即可:- 在你的组合操作实现逻辑中,每次发起下一个底层异步操作前,通过
asio::get_associated_cancellation_slot获取和完成令牌绑定的取消槽 - 检查取消槽是否已触发,若已触发则直接调用用户传入的完成处理函数,返回
asio::error::operation_aborted错误,终止后续逻辑
- 在你的组合操作实现逻辑中,每次发起下一个底层异步操作前,通过
- 按上述规则实现的自定义组合操作,和内置组合操作的取消用法完全一致,外部调用方同样可以用
cancellation_signal触发取消,不需要感知内部实现细节。
内容的提问来源于stack exchange,提问作者MHebes
相关产品推荐
相关产品推荐

