可以总结下面几个步骤(步骤2和3的顺序大多情况可以调换):
-
创建
promise
和future
对象:开始是通过创建一个std::promise
对象。然后可以从这个promise
获取返回一个std::future
对象,返回的对象可以拷贝到创建的future对象。 -
(也可以为step3)设置值或异常:通过
promise
的set_value
方法设置有效的结果,或者使用set_exception
方法设置一个异常(也可以用一个自定义的默认构造对象作为异常值)。这些操作定义了异步操作的最终输出。 -
(也可以为step2)关联
promise
和future
:通过promise
对象的get_future
方法获取一个std::future
对象。这一步确实可以在set_value
之前或之后进行,但通常在设置值之前获取future
,这样可以确保当值被设置时,future
已经准备好来接收这个值。 -
获取结果:通过
future
对象的get
方法来获取promise
中设置的结果。如果结果尚未被设置,调用get
会阻塞当前线程,直到promise
的值被设置。对于std::future
,一旦调用了get
方法,该future
对象就不能再用于获取结果了,对于std::shared_future
,则可以多次调用get
,每次都返回相同的结果。 -
future
对象的拷贝行为:这里稍要区分std::future
和std::shared_future
:- 对于
std::future
,它不支持拷贝操作,只能被移动。因此,不能简单地通过拷贝std::future
对象来访问相同的结果。一旦std::future
的结果被获取,它就处于无效状态。 - 对于
std::shared_future
,它允许拷贝,并且拷贝之后的所有std::shared_future
对象确实访问的是相同的内存中的结果,允许多次调用get
方法获取结果。
- 对于
示例代码如下:
#include <future>
#include <iostream>
#include <thread>
void asyncTask(std::promise<int>&& prom) {
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
prom.set_value(42); // 设置promise的结果
}
int main() {
std::promise<int> prom; // 创建一个promise对象
std::future<int> fut = prom.get_future(); // 从promise获取future对象
std::thread th(asyncTask, std::move(prom)); // 启动一个异步任务
// 在等待结果时,可以做一些其他的事情...
std::cout << "Waiting for the result..." << std::endl;
int result = fut.get(); // 获取异步操作的结果,如果尚未准备好会阻塞在这里
std::cout << "Result from async task: " << result << std::endl;
th.join(); // 等待异步任务结束
// 演示std::shared_future的能力
std::shared_future<int> sharedFut = std::async(std::launch::async, []() -> int {
return 88;
});
// 拷贝shared_future,并从多个拷贝中获取相同的结果
auto sharedFutCopy1 = sharedFut;
auto sharedFutCopy2 = sharedFut;
std::cout << "Result from sharedFut: " << sharedFut.get() << std::endl;
std::cout << "Result from sharedFutCopy1: " << sharedFutCopy1.get() << std::endl;
std::cout << "Result from sharedFutCopy2: " << sharedFutCopy2.get() << std::endl;
return 0;
}