概念簡介
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()獲取}