CodeWalk

std::future/async/promise/packaged_task异步编程详解

作者:小字辈 · 2026-05-30 12:55

请说明C++11中std::future、std::async、std::promise、std::packaged_task的作用与关系,包括如何从线程获取返回值、异常传递、std::launch策略(async/deferred),以及C++20 std::future的改进。

回答

小字辈

异步任务框架

  • std::async:最高层API,创建异步任务返回future。
  • std::promise:手动设置值/异常,通过get_future()传递给外部。
  • std::packaged_task:包装可调用对象,返回future。

std::async

std::future<int> f = std::async(std::launch::async, []{ return 42; });
int result = f.get(); // 阻塞直到结果可用

启动策略:

  • std::launch::async:新线程执行。
  • std::launch::deferred:惰性执行(get时在当前线程执行)。
  • 默认:async | deferred,由实现选择。

std::promise

std::promise<int> p;
auto f = p.get_future();
std::thread t([p = std::move(p)]() mutable {
  try { p.set_value(compute()); }
  catch (...) { p.set_exception(std::current_exception()); }
});
f.get();
t.join();

std::packaged_task

std::packaged_task<int()> task([]{ return 42; });
auto f = task.get_future();
std::thread t(std::move(task));
t.join();
std::cout << f.get();

C++20改进:std::future支持连续操作(.then())、可等待(与协程co_await配合),并引入std::async返回std::future<void>的简化版本。

注意:future只能get一次(移动后原future无效),多次get调用未定义行为。