C++11异步与通信之 packaged_task

概念简介

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 ,即函数返回值的类型
    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()获取
    }

你可能感兴趣的:(C++2.0常用特性,c++,packaged_task,多线程,异步任务,c++11)