跳转到内容

C++ 异步任务

来自代码酷
Admin留言 | 贡献2025年4月28日 (一) 21:26的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

C++异步任务是C++多线程编程中的重要概念,通过`<future>`和`<thread>`等头文件提供的工具,允许开发者以非阻塞方式执行任务并获取结果。本页详细介绍其核心组件、使用方法和实际应用场景。

概述[编辑 | 编辑源代码]

异步任务(Asynchronous Task)允许程序在后台执行耗时操作(如计算、I/O),同时主线程继续处理其他任务。C++11引入的`std::async`、`std::future`和`std::promise`为此提供了标准化支持。

关键优势包括:

  • 非阻塞执行:主线程无需等待任务完成。
  • 结果获取:通过`future`对象延迟获取返回值或异常。
  • 资源管理:自动处理线程生命周期。

核心组件[编辑 | 编辑源代码]

std::async[编辑 | 编辑源代码]

启动异步任务,返回`std::future`对象。语法:

  
#include <future>  
#include <iostream>  

int compute() {  
    return 42; // 模拟耗时计算  
}  

int main() {  
    std::future<int> result = std::async(std::launch::async, compute);  
    std::cout << "Main thread continues..." << std::endl;  
    std::cout << "Result: " << result.get() << std::endl; // 阻塞直至结果就绪  
    return 0;  
}

输出:

  
Main thread continues...  
Result: 42  

参数`std::launch::async`强制创建新线程,而`std::launch::deferred`延迟执行(调用`get()`时运行)。

std::future[编辑 | 编辑源代码]

表示异步操作的结果,提供以下方法:

  • `get()`:获取结果(若未就绪则阻塞)。
  • `wait()`:等待结果就绪。
  • `valid()`:检查结果是否可用。

std::promise[编辑 | 编辑源代码]

允许显式设置值或异常,与`std::future`配对使用:

  
void set_value(std::promise<int>&& prom) {  
    prom.set_value(100);  
}  

int main() {  
    std::promise<int> prom;  
    std::future<int> fut = prom.get_future();  
    std::thread t(set_value, std::move(prom));  
    std::cout << "Future value: " << fut.get() << std::endl;  
    t.join();  
    return 0;  
}

实际案例[编辑 | 编辑源代码]

并行计算[编辑 | 编辑源代码]

计算两个向量的点积,分解为多个异步任务:

  
#include <vector>  
#include <numeric>  
#include <future>  

double dot_product(const std::vector<double>& a, const std::vector<double>& b, size_t start, size_t end) {  
    return std::inner_product(a.begin() + start, a.begin() + end, b.begin() + start, 0.0);  
}  

int main() {  
    std::vector<double> a(1000, 1.0), b(1000, 2.0);  
    auto fut1 = std::async(std::launch::async, dot_product, std::ref(a), std::ref(b), 0, 500);  
    auto fut2 = std::async(std::launch::async, dot_product, std::ref(a), std::ref(b), 500, 1000);  
    double result = fut1.get() + fut2.get();  
    std::cout << "Dot product: " << result << std::endl; // 输出 2000  
}

超时处理[编辑 | 编辑源代码]

使用`std::future::wait_for`实现超时控制:

  
std::future<int> fut = std::async([](){  
    std::this_thread::sleep_for(std::chrono::seconds(5));  
    return 123;  
});  

if (fut.wait_for(std::chrono::seconds(2)) == std::future_status::timeout) {  
    std::cout << "Task timeout\n";  
} else {  
    std::cout << "Result: " << fut.get() << "\n";  
}

进阶主题[编辑 | 编辑源代码]

异常传递[编辑 | 编辑源代码]

异步任务中的异常会通过`future::get()`重新抛出:

  
auto fut = std::async([](){  
    throw std::runtime_error("Error in async task");  
});  

try {  
    fut.get();  
} catch (const std::exception& e) {  
    std::cerr << "Caught: " << e.what() << std::endl;  
}

线程池集成[编辑 | 编辑源代码]

结合自定义线程池优化资源使用(伪代码):

  
ThreadPool pool(4); // 4个工作线程  
auto fut = pool.enqueue([](){ return /* ... */; });

性能考虑[编辑 | 编辑源代码]

  • 频繁创建线程的开销较大,建议复用线程(如线程池)。
  • `std::async`默认策略由实现决定,显式指定`std::launch::async`或`deferred`以避免歧义。

总结[编辑 | 编辑源代码]

C++异步任务简化了多线程编程,适合I/O密集型或可并行计算场景。通过`future`/`promise`模型,开发者可以高效管理任务依赖和结果同步。

graph LR A[主线程] --> B[启动异步任务] B --> C[std::async] C --> D[返回 std::future] D --> E[主线程继续执行] E --> F[调用 future.get()] F --> G[阻塞/获取结果]