c++11多线程之packaged_task<>介绍与实例
本節討論c++11中std::packaged_task的特性與使用方法
std::packaged_task<>
std::packaged_task<>是一個類模板,代表一個異步任務。封裝了
1、可調用實體,即函數,lambda函數或函數對象
2、一個共享狀態,通過關聯的回調來存儲返回的值或拋出的異常。
現在我們想在一個單獨的線程中執行該函數,但是我們如果在其他線程結束的情況下在主線程中獲取結果或異常返回?
一種方法是更改函數聲明并在函數中傳遞std::promise。在傳遞線程函數中的std::promise<>對象之前,將相關的std::future<>從中取出并保存在主線程中。現在,在線程函數返回其值之前,應該在傳入的std::promise參數中設置它,所以它可以在主線程的相關std::future對象中使用。參考第八節
******************************************
但是,如果我們使用std::packaged_task<>,則可以避免創建std::promise和更改函數代碼。
使用packaged_task<>創建異步任務
std::packaged_task<>可以包裝一個標準函數,使其適用于作為異步功能運行。
當std::packaged_task<>在一個單獨的線程中運行時,它會調用相關的回調函數,并將返回值或異常存儲在其內部共享狀態中。該值可以通過std :: future <>對象在其他線程或主函數中訪問。
從上面提到的函數創建一個packaged_task<>,運行于獨立的線程并從其future<>對象獲取返回值。創建std::packaged_task<> 對象
std::packaged_task<>對象是一個類模板,因此我們需要將模板參數傳遞給packaged_task<>,即可調用函數的類型。
?
獲取future對象
//從packaged_task<>獲取相關future<> std::future<std::string> result = task.get_future();?傳遞packaged_task<>給線程
std::packaged_task<>可移動,但是不可復制,所以我們需要將它傳遞給線程
//傳遞packaged_task<>給線程以異步運行 std::thread th(std::move(task), "Arg");由于packaged_task只可以移動,不可以復制,因此我們在將它移動到線程之前從它那里取出了 std::future<>對象。
線程將會執行這個任務,該任務在內部調用相關的可調用實體,例如我們的函數getDataFromDB()。
當這個函數給出返回值時,std::packaged_task<>將其設置為關聯的共享狀態,getDataFromDB()返回的結果或異常最終會在關聯的未來對象中可用。
get()函數將會阻塞調用線程,直到有可調用的實體返回,并且std::packaged_task<>將數據設置為其可共享的狀態。
完整的例子如下:
#include <iostream> #include <thread> #include <future> #include <string>//從DB獲取數據 std::string getDataFromDB(std::string token) {//獲取數據std::string data = "Data fetched from DB by Filter :: " + token;return data; }int main() {//創建封裝回調函數的packaged_task<>std::packaged_task<std::string(std::string)> task(getDataFromDB);//從packaged_task<>獲取相關的future<>std::future<std::string> result = task.get_future();//將packaged_task傳遞給線程以異步運行std::thread th(std::move(task), "Arg");//join線程,阻塞直到線程完成時返回th.join();//獲取packaged_task<>的結果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0; }?輸出:
Data fetched from DB by Filter :: Arg我們可以在同一行,用lambda函數或函數對象創建一個packaged_task
?使用lambda函數創建packaged_task
#include <iostream> #include <thread> #include <future> #include <string>int main() {//創建封裝了lambda函數的packaged_task<>std::packaged_task<std::string(std::string)> task([](std::string token) {std::string data = "Data From " + token;return data;});//從packaged_task<>獲取相關的future<>std::future<std::string> result = task.get_future();//將packaged_task傳遞給線程以異步運行std::thread th(std::move(task), "Arg");//join線程,阻塞直到線程完成時返回th.join();//獲取packaged_task<>的結果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0; }?輸出:
Data fetched from DB by Filter :: Arg使用函數對象創建packaged_task
#include <iostream> #include <thread> #include <future> #include <string>//從DB獲取數據的函數對象 struct DBDataFetcher {std::string operator ()(std::string token) {std::string data = "Data From " + token;return data;} };int main() {//使用函數對象創建packaged_taskstd::packaged_task<std::string(std::string)> task(std::move(DBDataFetcher()));//從packaged_task<>獲取相關的future<>std::future<std::string> result = task.get_future();//將packaged_task傳遞給線程以異步運行std::thread th(std::move(task), "Arg");//join線程,阻塞直到線程完成時返回th.join();//獲取packaged_task<>的結果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0; }?輸出:
Data fetched from DB by Filter :: Arg原文鏈接:https://blog.csdn.net/lijinqi1987/article/details/78909524
總結
以上是生活随笔為你收集整理的c++11多线程之packaged_task<>介绍与实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博通第一财季营收 89.15 亿美元,净
- 下一篇: C++11之std::async使用介绍