c++11提供了异步操作类,主要包括std::future、std::promise和std::package_task。另外还有更高层次的异步操作std::async。
std::future
thread库提供了std::future用来访问异步操作的结果。future,顾名思义,代表的是未来的一个期待值,future提供了获取异步操作结果的通道。
future_status有3种状态,如下所示:
1)Deferred:异步操作还未开始;
2)Ready:异步操作已经完成;
3)Timeout:异步操作超时;
获取future结果有3种方式:
1)get:等待异步操作结束并返回结果;
2)wait:等待异步操作完成,无返回值;
3)wait_for:超时等待返回结果;
例如:
std::future_status status;
status = future.wait_for(std::chrono::seconds(1));
std::promise
std::promise将数据与future绑定起来,为获取线程函数中的某个值提供便利,在线程函数中为外面传进来的promise赋值,在线程函数执行完成后可以通过promise的future获取该值了。
例如:
std::promise<int> ptr;
std::thread t([](std::promise<int>& p) {
p.set_value_at_thread_exit(9);
}, std::ref(ptr));
std::future<int> f = ptr.get_future();
auto r = f.get();
std::package_task
std::package_task包装了一个可调用的包装类(类似于function、lambda expression、bind expression和another function object),将函数和future绑定起来,便于异步调用。
例如:
std::packaged_task<int()> task([]() { return 2; });
std::thread t1(std::ref(task));
std::future<int> f1 = task.get_future();
auto r1 = f1.get();
三者联系
std::package_task和std::promise内部都有future以便访问异步结果,可以这样理解,std::package_task包装的是一个函数,std::promise包装的是一个值。
future被promise和package_task用来作为异步操作或者异步结果的连接通道,用std::future和std::shared_future来获取异步调用结果。future是不可拷贝的,只能移动,shared_future是可以拷贝的,当需要将future放到容器中则需要使用shared_future。
示例代码
#include <iostream>
#include <utility>
#include <future>
#include <thread>
#include <vector>
using namespace std;
int foo(int i)
{
return i + 1;
}
int main()
{
std::packaged_task<int(int)> task(foo); //将函数与future绑定起来
std::future<int> f0 = task.get_future(); //获取future
std::thread(std::move(task), 2).detach();
int iValue = f0.get();
cout << "the result is " << iValue << endl;
std::vector<std::shared_future<int>> vec;
std::shared_future<int> f1 = std::async(std::launch::async, [](int m, int n) {
return m + n;
}, 1, 2);
vec.push_back(f1);
cout << "the shared_future is " << vec[0].get() << endl;
system("pause");
return 0;
}
运行结果:
the result is 3
the shared_future is 3
注意:
std::vector<std::shared_future<int>> vec;
auto f1 = std::async(std::launch::async, [](int m, int n) {
return m + n;
}, 1, 2);
vec.push_back(f1);
此处如写auto让其自行推导类型,在vs2015编译会报这种错误:
无法将参数 1 从“std::future<_ret>”转换为“std::shared_future<_ty> &&
async
如上例所示,std:;async是更高层次的异步操作,可以用来直接创建异步的task,异步任务返回的结果保存在future中。
std::async的原型:
async(std::launch::async | std::launch::deferred, f, args...)
1)std::launch::async:在调用async时就开始创建线程
2) std::launch::deferred:延迟加载方式创建线程。调用async时不创建线程,直到调用了future的get或者wait时才创建线程。
f代表线程函数,args...代表线程函数的参数。