asio::executor由io_context等对象隐式提供,调用post()/dispatch()时自动提取当前上下文关联的executor;dispatch()尝试内联执行,post()总是入队;strand_executor是串行化wrapper,不管理线程;自定义executor需严格满足Executor概念。

asio::executor 是怎么被调度器选中的
它不是你手动“创建”后塞进某个地方的,而是由 io_context、thread_pool 或其他 executor-aware 对象隐式提供或传播的。你调用 post()、dispatch()、defer() 时,底层会从当前执行上下文(比如 handler 的关联 executor)中提取一个 executor,再把任务丢进去。
常见错误现象:std::bad_cast 或编译失败,出现在你试图把一个泛型 executor 强转成 io_context::executor_type 却没做类型检查;或者在 strand 外部直接捕获并保存 get_executor() 返回值,结果该 executor 生命周期短于使用它的 lambda。
- 使用场景:多数时候你不需要显式持有
executor,除非要跨线程传递执行上下文(比如从主线程把任务发到thread_pool) -
executor是可拷贝、可比较、可默认构造的,但不保证可赋值(C++20 起部分实现支持) - 性能影响:频繁调用
get_executor()开销极小,但滥用require()(如反复要求execution::outstanding_work.tracked)可能引入分支判断或额外状态维护
为什么 post() 和 dispatch() 行为不同
区别不在 executor 本身,而在调用时的执行上下文是否“正在该 executor 关联的上下文中运行”。dispatch() 会尝试内联执行(如果当前线程已处于目标 executor 控制下),而 post() 总是入队延迟执行。
容易踩的坑:在 io_context::run() 线程里对同一个 io_context 的 executor 调用 dispatch(),看似省了一次入队,但如果 handler 里又调了 dispatch(),可能引发栈溢出;反过来,在非 io 线程里误用 dispatch(),实际退化为 post(),但语义上你却以为“一定内联”,导致调试困难。
立即学习“C++免费学习笔记(深入)”;
- 参数差异:
dispatch()和post()接口完全一致,仅语义不同 - 兼容性影响:C++17 下
dispatch()行为依赖 executor 实现;C++20execution::executor概念更明确,但 asio 当前主干仍以传统模型为主 - 示例:
auto ex = my_socket.get_executor(); dispatch(ex, []{ /* 可能立即跑 */ }); post(ex, []{ /* 一定排队 */ });
strand_executor 是 executor 吗
是,但它是个 wrapper,不是独立调度器。它不拥有线程,也不管理队列,只保证其内部任务串行化——靠的是把所有任务都转发给它封装的那个底层 executor(比如 io_context::executor_type),并在转发前加锁或原子标记。
常见错误现象:多个 strand 共享同一个底层 executor,但你以为“每个 strand 都有自己线程”,结果高并发下依然出现争抢;或者把 strand 的 executor 传给 thread_pool,发现任务全卡在 strand 锁里,吞吐暴跌。
- 使用场景:保护共享数据结构,而非隔离 CPU 资源
- 性能影响:每次通过 strand 提交任务都有一次原子操作或 mutex 获取开销;过度细分 strand(比如每个对象一个)反而增加竞争
- 注意:
strand::get_executor()返回的是带串行语义的 executor,但它的query(execution::context)仍返回原始io_context&,别误以为它换了调度器
自定义 executor 在 asio 里到底能不能用
能,但限制很具体:必须满足 Executor 概念(C++17 起),即提供 execute() 成员函数,并支持 query()、require()、prefer()(可选)。asio 官方不鼓励手写,因为漏掉任意一个 trait 都可能导致 undefined behavior。
最容易被忽略的一点:你的自定义 executor 如果不能正确处理嵌套调用(比如在 execute() 内又调 post() 到自己),就会死锁或无限递归。asio 自带的 executor(io_context::executor_type、thread_pool::executor_type)都经过严格测试,覆盖了 cancel、stop、join 等边界。
- 参数差异:自定义 executor 的
execute()必须接受一个可调用对象(通常为Function&&),且不能抛异常(否则 asio 可能终止程序) - 兼容性影响:C++20
std::execution的 executor 模型和 asio 当前模型不完全兼容,混用需谨慎 - 建议:优先用
thread_pool+strand组合,而不是从零造 executor;真需要定制,先 fork asio 的system_executor改起



















