
std::async是 C11 引入的一个用于简化异步编程的工具它可以启动一个异步任务并返回一个std::future对象用于获取任务的结果。std::async用于简化异步编程的工具它适合多种场景尤其是在需要异步执行任务并可能获取其结果时。对应std::thread promisefuture基本语法#include future std::futureResultType future std::async(LaunchPolicy, Function, Args...);ResultType任务的返回类型。LaunchPolicy启动策略决定任务如何执行。Function要执行的函数或可调用对象。Args...传递给函数的参数。#include future int heavy_task() { /* 长时间计算 */ } int main() { auto fut1 std::async(std::launch::async, heavy_task); // ...主线程干别的...此刻 heavy_task 已在后台线程并行运行 int r fut1.get(); // 若任务未完成这里阻塞直到完成 return 0; }// 真正的异步封装返回 future 让外面去等 template class F auto run_async_real(F f) { // 返回 future把控制权交给 main 函数 return std::async(std::launch::async, [func std::forwardF(f)]() - std::optionalstd::invoke_result_tF { try { return func(); } catch (...) { return std::nullopt; } }); } // 用法 int main() { // 1. 发射异步任务 auto fut run_async_real(heavy_task); // 2. 主线程此时没有被阻塞可以去干别的了 do_other_things_in_main_thread(); // 3. 别的事干完了再来收割结果这时候才阻塞 if (auto r fut.get()) { int val *r; } }遇到std::async你的第一反应应该是这个任务的结果我最终一定要拿到通过get或wait。如果你发现你的需求是“启动一个任务不管它了”或者“一定时间拿不到结果就抛弃它”那么说明std::async根本不适合你的场景请果断换用std::thread::detach配合值拷贝、std::jthread或者专业的线程池组件。1 启动策略Launch Policystd::async的启动策略通过std::launch枚举指定std::launch::async强制异步执行任务会在一个新线程中执行。如果资源不足可能会抛出std::system_error异常。std::launch::deferred延迟执行任务会在调用std::future::get()或std::future::wait()时在当前线程中执行。不会创建新线程。默认策略如果不指定策略std::async的实现可以选择异步或延迟执行。例如std::async(Function, Args...)。2 返回值std::async返回一个std::future对象用于获取异步任务的结果。std::future提供了以下常用方法get()获取任务的结果。如果任务未完成会阻塞当前线程直到结果可用。只能调用一次调用后std::future对象变为无效。wait()等待任务完成但不获取结果。wait_for()等待一段时间返回任务的状态std::future_status::ready、std::future_status::timeout。wait_until()等待直到某个时间点返回任务的状态。valid()检查std::future是否关联了一个有效的共享状态。3 示例代码3.1. 基本用法#include iostream #include future #include thread int task(int x, int y) { std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作 return x y; } int main() { // 启动异步任务 std::futureint future std::async(std::launch::async, task, 10, 20); // 主线程继续执行其他任务 std::cout Main thread is working... std::endl; // 获取异步任务的结果 int result future.get(); std::cout Result: result std::endl; return 0; }3.2. 使用延迟策略#include iostream #include future int task(int x, int y) { return x y; } int main() { // 启动延迟任务 std::futureint future std::async(std::launch::deferred, task, 10, 20); // 主线程继续执行其他任务 std::cout Main thread is working... std::endl; // 获取延迟任务的结果此时任务才会执行 int result future.get(); std::cout Result: result std::endl; return 0; }3.3. 检查任务状态#include iostream #include future #include thread int task(int x, int y) { std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作 return x y; } int main() { // 启动异步任务 std::futureint future std::async(std::launch::async, task, 10, 20); // 检查任务状态 while (future.wait_for(std::chrono::milliseconds(100)) ! std::future_status::ready) { std::cout Task is still running... std::endl; } // 获取任务结果 int result future.get(); std::cout Result: result std::endl; return 0; }3.4. 处理异常如果异步任务中抛出了异常异常会通过std::future::get()传递到调用线程。#include iostream #include future #include stdexcept int task(int x, int y) { if (y 0) { throw std::runtime_error(Division by zero!); } return x / y; } int main() { // 启动异步任务 std::futureint future std::async(std::launch::async, task, 10, 0); // 捕获异常 try { int result future.get(); std::cout Result: result std::endl; } catch (const std::exception e) { std::cerr Exception: e.what() std::endl; } return 0; }3.5. 并行执行多个任务#include iostream #include future #include vector int task(int id) { std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作 return id * 10; } int main() { std::vectorstd::futureint futures; // 启动多个异步任务 for (int i 0; i 5; i) { futures.push_back(std::async(std::launch::async, task, i)); } // 获取所有任务的结果 for (auto fut : futures) { int result fut.get(); std::cout Result: result std::endl; } return 0; }4 任务使用方式任务可以是函数、lambda 表达式、函数对象等。通过std::future::get()获取任务结果。4.1. 普通函数普通函数是最简单的任务函数形式。你可以直接将函数名传递给std::async。示例#include iostream #include future // 普通函数 int add(int a, int b) { return a b; } int main() { // 使用普通函数作为任务 std::futureint future std::async(std::launch::async, add, 10, 20); // 获取结果 int result future.get(); std::cout Result: result std::endl; return 0; }4.2. Lambda 表达式Lambda 表达式是一种匿名函数可以直接在代码中定义并传递给std::async。示例#include iostream #include future int main() { // 使用 lambda 表达式作为任务 std::futureint future std::async(std::launch::async, [](int a, int b) { return a b; }, 10, 20); // 获取结果 int result future.get(); std::cout Result: result std::endl; return 0; }4.3. 函数对象仿函数函数对象是一个类或结构体重载了operator()可以像函数一样调用。示例#include iostream #include future // 函数对象 struct Adder { int operator()(int a, int b) const { return a b; } }; int main() { // 使用函数对象作为任务 Adder adder; std::futureint future std::async(std::launch::async, adder, 10, 20); // 获取结果 int result future.get(); std::cout Result: result std::endl; return 0; }4.4. 成员函数如果任务是一个类的成员函数需要使用std::bind或 lambda 表达式来绑定对象和成员函数。示例#include iostream #include future #include functional // 用于 std::bind class Math { public: int add(int a, int b) { return a b; } }; int main() { Math math; // 使用成员函数作为任务 std::futureint future std::async(std::launch::async, Math::add, math, 10, 20); // 获取结果 int result future.get(); std::cout Result: result std::endl; return 0; }4.5. 带捕获的 Lambda 表达式Lambda 表达式可以捕获外部变量适合需要访问局部变量的场景。示例#include iostream #include future int main() { int x 10; int y 20; // 使用带捕获的 lambda 表达式作为任务 std::futureint future std::async(std::launch::async, [x, y] { return x y; }); // 获取结果 int result future.get(); std::cout Result: result std::endl; return 0; }std::async支持多种形式的任务函数包括普通函数。Lambda 表达式。函数对象仿函数。成员函数。带捕获的 Lambda 表达式。函数指针。带状态的函数对象。5 其它应用5.1. 异步执行计算密集型任务当你有需要长时间运行的计算任务时可以使用std::async将这些任务放到后台线程中执行避免阻塞主线程。#include iostream #include future #include chrono #include thread double calculate_pi(long long iterations) { // 修复1long long double sum 0.0; for (long long i 0; i iterations; i) { double term 1.0 / (2LL * i 1); // 修复12LL sum (i % 2 0) ? term : -term; } return 4.0 * sum; } int main() { std::futuredouble pi_future std::async(std::launch::async, calculate_pi, 10000000000LL); // 主线程轮询wait_for 既当 sleep 又当状态检查 while (true) { std::cout Calculating π in the background... std::endl; auto status pi_future.wait_for(std::chrono::milliseconds(500)); if (status std::future_status::ready) { // 状态只看 future 这一份真相 std::cout π ≈ pi_future.get() std::endl; break; // 修复2完成后退出 } // timeout → 任务还在跑继续轮询 } std::cout Task completed! Main thread continues... std::endl; return 0; }5.2. I/O 密集型任务对于文件读写、网络请求等 I/O 操作通常会有较长的等待时间。使用std::async可以将这些操作放到后台线程中执行避免阻塞主线程。#include iostream #include future #include fstream #include string #include thread // 用于 std::this_thread::sleep_for // 异步读取文件内容 std::string read_file(const std::string filename) { std::ifstream file(filename); if (!file) { throw std::runtime_error(Failed to open file: filename); } return std::string((std::istreambuf_iteratorchar(file)), std::istreambuf_iteratorchar()); } // 异步写入文件内容 void write_file(const std::string filename, const std::string content) { std::ofstream file(filename); if (!file) { throw std::runtime_error(Failed to open file: filename); } file content; } int main() { // 异步读取文件 std::futurestd::string read_future std::async(std::launch::async, read_file, input.txt); // 主线程继续执行其他任务 std::cout Reading file in the background... std::endl; // 模拟主线程的其他工作 for (int i 0; i 5; i) { std::cout Main thread is working... ( i 1 /5) std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // 获取读取文件的结果 std::string file_content; try { file_content read_future.get(); std::cout File content read successfully! std::endl; } catch (const std::exception e) { std::cerr Error reading file: e.what() std::endl; return 1; } // 异步写入文件 std::futurevoid write_future std::async(std::launch::async, write_file, output.txt, file_content); // 主线程继续执行其他任务 std::cout Writing file in the background... std::endl; // 模拟主线程的其他工作 for (int i 0; i 5; i) { std::cout Main thread is working... ( i 1 /5) std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // 等待写入操作完成 try { write_future.get(); std::cout File content written successfully! std::endl; } catch (const std::exception e) { std::cerr Error writing file: e.what() std::endl; return 1; } return 0; }5.3并行执行多个任务当你有多个独立的任务需要并行执行时可以使用std::async启动多个异步任务并通过std::future获取它们的结果。#include iostream #include future #include vector int task(int id) { std::this_thread::sleep_for(std::chrono::seconds(1)); return id * 10; } int main() { std::vectorstd::futureint futures; // 启动多个异步任务 for (int i 0; i 5; i) { futures.push_back(std::async(std::launch::async, task, i)); } // 获取所有任务的结果 for (auto fut : futures) { std::cout Result: fut.get() std::endl; } return 0; }5.4 异常处理std::async支持异常传播。如果异步任务中抛出了异常异常会通过get()传递到调用线程。#include iostream #include future void task() { throw std::runtime_error(Something went wrong!); } int main() { // 启动异步任务 std::futurevoid fut std::async(std::launch::async, task); // 捕获异常 try { fut.get(); } catch (const std::exception e) { std::cerr Caught exception: e.what() std::endl; } return 0; }5.5任务分解与合并对于可以分解为多个子任务的问题可以使用std::async并行执行子任务然后在主线程中合并结果。#include iostream #include future #include vector int sub_task(int start, int end) { int sum 0; for (int i start; i end; i) { sum i; } return sum; } int main() { // 分解任务 std::futureint fut1 std::async(std::launch::async, sub_task, 1, 50); std::futureint fut2 std::async(std::launch::async, sub_task, 51, 100); // 合并结果 int total fut1.get() fut2.get(); std::cout Total sum: total std::endl; return 0; }不要多次调用.get()pi_future.get()被调用后pi_future对象变为无效状态。如果之后再次调用pi_future.wait_for()就会触发std::future_error异常。std::condition_variable实现生产者和消费者之间的协调后续使用。参考C 创建线程的五种类型