0Pricing
C++ Academy · 课时

异步任务与等待器类型

使用自定义等待器类型和 promise 类型组合异步任务

异步任务与等待器类型 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。

异步协程

异步任务会在 I/O 操作期间暂停,并在操作完成后恢复。将 co_await 与异步 API 结合使用,即可编写无需回调的异步代码。

Task 类型示意图

Task 封装了一个异步协程,并支持使用 co_await 进行链式调用。

template <typename T>
struct Task {
    struct promise_type;
    std::coroutine_handle<promise_type> handle;
    // ...
};

co_await 的机制

当编译器看到 co_await expr 时,它要求 expr 是一个可等待对象。可等待对象包含三个方法:

  • await_ready() — 返回 false 表示暂停,返回 true 表示跳过暂停
  • await_suspend(handle) — 指定暂停期间要执行的操作
  • await_resume() — 指定要交给调用代码的值

可等待对象示例:Sleep

一种会安排在延迟后恢复执行的可等待对象。

struct Sleep {
    std::chrono::milliseconds duration;
    bool await_ready() const { return false; }
    void await_suspend(std::coroutine_handle<> h) {
        std::thread([h, this] {
            std::this_thread::sleep_for(duration);
            h.resume();
        }).detach();
    }
    void await_resume() {}
};

Task<void> example() {
    co_await Sleep{500ms};
    std::cout << "after 500ms";
}

用于 HTTP 的可等待对象

库为 HTTP 请求、计时器和文件 I/O 提供的可等待对象。您可以像使用同步调用一样组合它们。

Task<std::string> fetch() {
    auto data = co_await http_get("/api/data");
    co_return data;
}

组合任务

在一个任务中等待另一个任务,就可以将它们串联起来。外层任务会暂停,直到内层任务完成。

Task<int> outer() {
    int x = co_await inner_a();
    int y = co_await inner_b();
    co_return x + y;
}

并行任务

对于并行异步工作,请先启动任务,不要立即逐个等待,然后再等待它们全部完成。

Task<int> sum_tasks() {
    auto a = inner_a();
    auto b = inner_b();
    int x = co_await a;
    int y = co_await b;
    co_return x + y;
}

异常传播

异步任务中抛出的异常可以捕获到 promise 的 unhandled_exception 中,并在等待方重新抛出。

取消

标准库目前还没有提供取消原语。库(cppcoro、boost.cobalt)会自行构建取消机制,通常通过取消令牌或停止源实现。

Boost.Asio 集成

Asio 原生支持协程。您可以对 async_read、async_write 和类似操作使用 co_await。这是目前最简洁的 C++ 异步 I/O 方案。

性能

恢复协程的开销远低于切换线程。编译器通常会将状态机的一部分内联。请进行性能分析,以确认您的可等待对象调用链能够顺利编译。

未来方向

C++23 加入了 std::generator 并带来了一些改进。C++26 可能会引入 std::execution(发送方/接收方),这是一种更通用的异步框架,并可与协程互操作。

快速检查

可等待类型需要哪三个方法?

小结

异步任务将 co_await 与可等待对象结合起来,从而编写无需回调的异步代码。可等待对象包含 await_ready、await_suspend 和 await_resume。库(cppcoro、Asio)提供现成的任务和可等待对象类型。

常见问题解答

「异步任务与等待器类型」课时是免费的吗?

是的 — 「异步任务与等待器类型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。

「异步任务与等待器类型」这节课中我会学到什么?

使用自定义等待器类型和 promise 类型组合异步任务 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C++ Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「异步任务与等待器类型」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C++ Academy 课中编写并运行代码吗?

能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 协程概念:co_await、co_yield、co_return
  2. 实现一个简单的生成器
  3. 异步任务与等待器类型
  4. 协程帧分配
← 返回 C++ Academy