C++26新异步模型与现有异步编程模型有何差异?
C++新异步编程模型:Schedulers、Receivers、Senders的交互与对比
一、三者如何构建新异步模型
这三个组件是一套推模式异步体系的核心,各司其职又紧密配合:
- Senders:负责发起异步任务,最终会产出结果、错误信号或取消通知,但它不处理这些输出,只负责把它们传递给绑定的Receiver。你可以把它理解成"异步任务的发起者+结果传递者"。
- Receivers:定义了如何处理异步任务的输出——通过
set_value接收结果、set_error处理错误、set_done响应取消。它是异步任务的"最终处理者"。 - Schedulers:决定Receiver的执行时机和上下文,比如是在当前线程、线程池还是特定IO线程上运行Receiver的处理逻辑。
完整的异步流程是这样的:
- 创建一个Sender,定义要执行的异步任务(比如IO操作、计算任务),并绑定对应的Receiver;
- Sender向Scheduler申请为Receiver分配执行上下文;
- 异步任务完成后,Sender把结果/错误/取消信号传递给Receiver;
- Scheduler调度Receiver的处理逻辑在指定的上下文里执行。
举个简化的代码示例,能直观体现这套逻辑:
// 定义Receiver:处理异步结果 struct ResultHandler { void set_value(int calc_result) { std::cout << "异步计算完成,结果:" << calc_result << std::endl; } void set_error(std::exception_ptr err) { try { std::rethrow_exception(err); } catch (const std::exception& e) { std::cerr << "任务出错:" << e.what() << std::endl; } } void set_done() { std::cout << "任务被取消" << std::endl; } }; // 获取线程池调度器(C++标准草案中的组件) auto thread_pool_sched = std::execution::thread_pool(); // 创建Sender:发起异步计算任务 auto calc_sender = std::execution::make_sender([&](auto&& receiver) { // 模拟异步计算:在后台线程执行 std::thread([receiver = std::move(receiver)]() mutable { int result = 100 + 200; // 通知Scheduler调度Receiver处理结果 std::execution::schedule(thread_pool_sched, std::move(receiver)).set_value(result); }).detach(); }); // 绑定Sender和Receiver,触发整个异步流程 std::execution::connect(calc_sender, ResultHandler{});
二、与传统异步模型的核心差异
1. 对比std::future/std::promise
- 模式不同:
future是拉模式——需要主动调用get()阻塞或轮询结果;新模型是推模式,结果自动推送给Receiver,无需主动等待,避免了不必要的阻塞。 - 组合能力:
future的组合非常繁琐,比如要等待多个future完成,得手动写同步逻辑;新模型的Sender支持then、when_all、when_any等原生组合操作,能轻松搭建复杂的异步流水线。 - 错误与取消:
future的取消机制直到C++20才通过std::stop_token有限支持,错误处理也依赖get()抛出异常;新模型的Receiver原生支持错误和取消信号的处理,逻辑更统一、灵活。
2. 对比传统Executors
- 职责拆分:传统Executors(比如
std::executor)只负责调度执行任务,没有明确区分任务发起、结果处理的角色;新模型把这三个职责拆成独立组件,边界更清晰,扩展性更强。 - 类型安全:新模型基于模板实现,编译期就能校验组件的兼容性,没有类型擦除带来的运行时开销;而传统的
std::any_executor为了通用性牺牲了类型安全和性能。 - 异步流程表达:Executors只能提交单个独立任务,无法表达任务间的依赖关系;新模型的Sender可以组合多个异步操作,清晰表达"先做A,再用A的结果做B"这类依赖逻辑。
3. 对比Boost.ASIO
- 标准化:新模型是C++标准库的原生组件,无需依赖第三方库;Boost.ASIO是第三方库,虽然部分功能被纳入标准(比如
std::asio),但整体模型和标准新异步体系仍有差异。 - 通用性:Boost.ASIO主要面向IO异步操作,设计围绕IO对象和回调;新模型是通用异步模型,既能处理IO任务,也能处理计算型异步任务,适用场景更广。
- 组合易用性:Boost.ASIO的异步任务组合需要借助
async_compose等工具,学习成本较高;新模型从设计之初就把组合性作为核心特性,提供了统一、直观的组合操作符。
内容的提问来源于stack exchange,提问作者Desmond Gold
相关产品推荐
相关产品推荐

