C++ 异步操作

std::future 是 C++11 中的标准库类,用于异步任务的管理和获取结果。它允许你在一个线程中启动一个异步任务,然后在另一个线程中等待任务完成并获取其结果。

以下是使用 std::future 的常见用法:

  1. 启动异步任务
std::future<int> result = std::async([]() {
    // 执行一些异步操作并返回一个结果
    return 42;
});

等待任务完成

result.wait(); // 阻塞等待任务完成

获取任务结果

int value = result.get(); // 获取任务的返回值

注意:在调用 get 之前,确保任务已经完成,否则它会阻塞等待任务完成。

检查任务是否完成

if (result.valid()) {
    // 任务已完成
} else {
    // 任务未完成
}

设置超时等待

std::future_status status = result.wait_for(std::chrono::seconds(2));
if (status == std::future_status::ready) {
    // 任务已完成
    int value = result.get();
} else if (status == std::future_status::timeout) {
    // 任务尚未完成,等待超时
} else if (status == std::future_status::deferred) {
    // 任务还未开始执行
}

共享状态

std::future 可以用于获取异步任务的结果,但一旦获取后,它不能再次用于其他操作。如果需要多次获取结果,可以使用 std::shared_future

示例:

/*****************************
std::async
******************************/

#include <iostream>
#include <functional>
#include <future>
#include <thread>
using namespace std;

int func(int num) { return num + 1; }

int main() {
    // auto : std::future<int>
    auto result = std::async(func, 5);

    // 阻塞等待任务完成
    result.wait();

    cout << result.get() << endl;

    return 0;
}

async 是比 futurepackaged_taskpromise 更高级的东西,它是基于任务的异步操作,通过 async 可以直接创建异步的任务,返回的结果会保存在 future 中,不需要像 packaged_taskpromise 那么麻烦


c++11 关于异步操作提供了 future 相关的类,

  • std::future
  • std::promise
  • std::packaged_task

std::futurestd::thread高级些,std::future 作为异步结果的传输通道,通过 get()可以很方便的获取线程函数的返回值,std::promise 用来包装一个值,将数据和 future 绑定起来,而 std::packaged_task 则用来包装一个调用对象,将函数和 future 绑定起来,方便异步调用。而std::future 是不可以复制的,如果需要复制放到容器中可以使用 std::shared_future

三者之间的关系

std::future 用于访问异步操作的结果,而 std::promisestd::packaged_task 在 future 高一层,它们内部都有一个 future,promise包装的是一个值,packaged_task 包装的是一个函数,当需要获取线程中的某个值,可以使用 std::promise,当需要获取线程函数返回值,可以使用 std::packaged_task

/*****************************
std::promise 与 std::future 配合使用
******************************/

#include <iostream>
#include <future>
#include <functional>
#include <thread>
using namespace std;

void func(std::future<int>& fut) {
    int x = fut.get();
    cout << "value: " << x << endl;
}

int main() {
    // 创建一个 std::promise 对象,它可以用来设置异步任务的结果,这里结果的类型是 int
    std::promise<int> prom; 

    // 通过 prom.get_future() 获取与 prom 共享状态的 std::future 对象
    std::future<int> fut = prom.get_future(); 

    // 创建一个新线程 t,并将 fut 传递给线程执行的函数 func
    std::thread t(func, std::ref(fut));

    // 在主线程中使用 prom.set_value(144) 设置异步任务的结果为 144
    prom.set_value(144); 
    
    // 等待线程结束
    t.join();

    return 0;
}
/*****************************
std::packaged_task 与 std::future 配合使用
******************************/

#include <iostream>
#include <functional>
#include <future>
#include <thread>
using namespace std;

int func(int num) {
    return num + 1;
}

int main() {
    // 创建 packaged_task 对象,包装了函数 func
    std::packaged_task<int(int)> task(func);

    // 通过从task获取相关的future 创建std::future对象 fut
    std::future<int> fut = task.get_future();

    // 创建新线程,并将 task移动到线程中
    std::thread t(std::move(task), 5);

    // 等待线程退出
    t.join();

    cout << "result " << fut.get() << endl;

    return 0;
}
posted @ 2023-10-20 09:51  洋綮  阅读(205)  评论(0)    收藏  举报