**C++中使用std::async与std::future实现异步计算的最佳实践**

在现代C++中,标准库提供了std::asyncstd::future来简化异步编程。与传统的线程管理方式相比,它们可以让我们更专注于业务逻辑,而不必关心线程的创建、同步和资源释放。下面我们从基础用法、异常处理、任务取消、线程池模拟以及性能对比等角度,系统阐述如何在实际项目中高效地使用这两者。

1. 基础用法

#include <future>
#include <iostream>

int compute(int a, int b) {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    return a + b;
}

int main() {
    std::future <int> fut = std::async(std::launch::async, compute, 5, 7);

    std::cout << "主线程继续执行...\n";
    int result = fut.get();   // 阻塞等待结果
    std::cout << "结果: " << result << '\n';
}
  • std::launch::async保证函数在新线程中立即执行。
  • std::launch::deferred则会把任务延迟到get()wait()时再执行。
  • 若省略第二个参数,编译器会根据std::launch::async | std::launch::deferred默认策略决定。

2. 异常与错误传播

当异步任务内部抛出异常时,std::future::get()会重新抛出同一异常,供调用方捕获。

int errorProne(int n) {
    if (n == 0) throw std::runtime_error("除零错误");
    return 10 / n;
}

int main() {
    auto f = std::async(std::launch::async, errorProne, 0);
    try {
        f.get();
    } catch (const std::exception& e) {
        std::cerr << "捕获异常: " << e.what() << '\n';
    }
}

3. 任务取消与超时

std::future本身不支持取消,但可以通过共享状态或标志配合实现。最常见的做法是使用`std::atomic

`或`std::condition_variable`,让任务定期检查是否应提前退出。 “`cpp #include #include std::atomic cancelFlag(false); void longTask() { for (int i = 0; i fut = std::async(std::launch::async, longTask); std::this_thread::sleep_for(std::chrono::seconds(3)); cancelFlag.store(true); fut.wait(); // 等待线程结束 } “` 若需超时,可在主线程使用`future::wait_for`或`future::wait_until`: “`cpp if (fut.wait_for(std::chrono::seconds(5)) == std::future_status::timeout) { std::cout #include #include #include #include #include class ThreadPool { public: ThreadPool(size_t threads); ~ThreadPool(); template auto enqueue(F&& f, Args&&… args) -> std::future>; private: std::vector workers; std::queue> tasks; std::mutex queue_mutex; std::condition_variable condition; bool stop; }; ThreadPool::ThreadPool(size_t threads) : stop(false) { for(size_t i=0;i task; { std::unique_lock lock(this->queue_mutex); this->condition.wait(lock, [this]{return this->stop || !this->tasks.empty();}); if(this->stop && this->tasks.empty()) return; task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } }); } ThreadPool::~ThreadPool() { { std::unique_lock lock(queue_mutex); stop = true; } condition.notify_all(); for(std::thread &worker: workers) worker.join(); } template auto ThreadPool::enqueue(F&& f, Args&&… args) -> std::future> { using return_type = typename std::invoke_result_t; auto task = std::make_shared>( std::bind(std::forward (f), std::forward(args)…)); std::future res = task->get_future(); { std::unique_lock lock(queue_mutex); if(stop) throw std::runtime_error(“enqueue on stopped ThreadPool”); tasks.emplace([task](){ (*task)(); }); } condition.notify_one(); return res; } “` ### 5. 性能考量 – **任务粒度**:若任务非常短小(

发表评论