std::future/async/promise/packaged_task异步编程详解
请说明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调用未定义行为。