C++11 std::async()基础用法示例

在 C++11 中引入的 std::async是一个用于异步执行任务的工具,它简化了多线程编程的复杂度,通过返回 std::future对象实现对异步任务结果的获取。
一、核心概念
std::async用于启动一个异步任务(可能在独立线程中执行),并返回一个 std::future对象,通过该对象可以:
-
阻塞等待任务完成并获取返回值(
future::get()); -
查询任务状态(
future::valid()、future::wait_for()等); -
异常传递(任务中的异常会延迟到
get()时抛出)。
二、函数原型与启动策略
std::async的声明如下:
template< class Function, class... Args >
std::future<typename std::result_of<Function(Args...)>::type>
async( Function&& f, Args&&... args );
template< class Function, class... Args >
std::future<typename std::result_of<Function(Args...)>::type>
async( std::launch policy, Function&& f, Args&&... args );
其中第二个模板参数是启动策略(std::launch枚举),控制任务的执行方式:
|
策略 |
说明 |
|---|---|
|
|
强制在新线程中异步执行任务(类似 |
|
|
延迟执行:任务不会立即启动,直到调用 |
|
默认策略(无显式指定) |
实现定义(通常是 `async |
三、基础用法示例
1. 最简用法(无显式策略)
#include <iostream>
#include <future>
#include <thread>
int compute(int a, int b) {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
return a + b;
}
int main() {
// 启动异步任务,返回 std::future<int>
auto future = std::async(compute, 2, 3);
// 主线程继续执行其他操作...
std::cout << "Main thread working...";
// 阻塞等待任务完成,获取结果
int result = future.get();
std::cout << "Result: " << result << std::endl; // 输出 5
return 0;
}
-
std::async(compute, 2, 3)启动异步任务,传递函数compute和参数2, 3。 -
future.get()阻塞主线程,直到任务完成并返回结果。
2. 显式指定启动策略
// 强制异步执行(新线程)
auto future_async = std::async(std::launch::async, compute, 2, 3);
// 延迟执行(当前线程同步执行)
auto future_deferred = std::async(std::launch::deferred, compute, 2, 3);
future_async.get(); // get()阻塞等待
future_deferred.get(); // 此时在当前线程同步执行 compute(2,3)
四、参数传递与引用语义
std::async支持传递任意可调用对象(函数、Lambda、函数对象等)和参数。若需传递引用,需用 std::ref包装:
#include <functional>
void modify(int& value) {
value = 100;
}
int main() {
int x = 0;
// 错误:直接传递引用会被复制(值语义)
// auto future = std::async(modify, x);
// 正确:用 std::ref 传递引用
auto future = std::async(modify, std::ref(x));
future.get();
std::cout << x << std::endl; // 输出 100(x 被修改)
return 0;
}
五、std::future 的常用接口
std::async返回的 std::future提供以下关键方法:
|
方法 |
说明 |
|---|---|
|
|
阻塞直到任务完成,返回结果(或抛出任务中的异常);只能调用一次。 |
|
|
阻塞直到任务完成;可多次调用。 |
|
|
阻塞最多 |
|
|
阻塞直到指定时间点。 |
|
|
检查 |
|
|
转换为 |
六、异常处理
异步任务中抛出的异常会被 std::future捕获,直到调用 get()时重新抛出:
int risky_compute(int x) {
if (x < 0) throw std::runtime_error("x is negative");
return x * 2;
}
int main() {
auto future = std::async(risky_compute, -1);
try {
int result = future.get(); // 抛出 std::runtime_error
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << ""; // 捕获异常
}
return 0;
}
七、注意事项
-
生命周期管理:
std::future析构时,若任务未完成且未被get()或wait(),可能导致程序终止(取决于实现)。若需共享结果,使用std::shared_future。 -
线程复用:
std::async不保证任务一定在新线程中执行(尤其是deferred策略或编译器优化),依赖具体实现。 -
性能开销:
相比手动管理
std::thread,std::async自动管理线程生命周期,但频繁创建小任务可能有额外开销(适合中高耗时任务)。
八、典型应用场景
-
并行计算:同时执行多个独立任务(如图像处理中的多区域计算)。
-
异步IO:发起IO操作后异步等待结果,避免阻塞主线程。
-
任务编排:结合
std::future::wait_for实现超时控制(如监控任务是否超时)。
总结
std::async是 C++11 中简化异步编程的核心工具,通过 std::future提供结果获取和状态查询能力。合理使用其启动策略和异常处理机制,可有效提升代码的并发性能和可维护性。

惠州西湖
更多推荐



所有评论(0)