概念简介
packaged_task
用于包装可调用目标(Callable)为一个对象,如lambda,普通函数,小括号重载等,用于异步调用。
其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中,和promise类似。
将函数的调用与函数返回值的获取分开调用,这样就给异步提供很大的便利。
猛的一看好像和std::bind
绑定器作用相似,可惜std::bind
返回的对象是同步的。
示例:函数在子线程执行,返回值可以在主线程异步获取
std::string Func()
{std::cout << "Thread t Call Func"<< std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));return "Return Thread t Func Result";
}int main()
{//将全局函数Func打包成异步调用对象std::packaged_task<std::string()> task(Func);//task调用后的结果将保存在result中//result的类型是std::future<std::string> ,即函数返回值的类型auto result = task.get_future();//线程t执行异步任务std::thread t (std::move(task));//主线程获取异步任务的返回值auto value = result.get();//打印结果std::cout << "Main Thread Get Return value = " << value << std::endl;t.join();return 0;
}
执行结果:
Thread t Call Func
Main Thread Get Return value = Return Thread t Func Result
补充:
有一些任务执行可能比较耗时,我们可以使用其提供的带时间的结果获取
- std::future_status::timeout 异步任务已经完成并返回结果。此时可以通过调用
std::future::get()
来获取异步任务的返回值; - std::future_status::ready 等待异步任务超时。此时可以选择等待更长时间再尝试获取结果,或者取消任务;
- std::future_status::deferred 异步任务被推迟执行。此时可以暂时不获取结果,等待后续需要时再执行异步任务,或者放弃执行异步任务。利用
std::future::deferred
策略将异步任务推迟到std::future::get()
方法调用时才执行,从而实现惰性求值。这种方式下,异步任务的执行被推迟,直到调用std::future::get()
方法时再执行。返回该状态意味着异步任务还未执行,并且只有调用std::future::get()
时才会执行。
if(result.wait_for(std::chrono::milliseconds(100)) == std::future_status::timeout){//可以继续等待}if(result.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready){//调用get()获取}if(result.wait_for(std::chrono::milliseconds(100)) == std::future_status::deferred){//调用get()获取}