(1) std::async 會返回一個 std::future 對象, 這個對象持有最終計算出來的結果. 當需要這個值時, 只需要調用對象的get()成員函數. 並且直到“期望”狀態為就緒的情況下, 線程才會阻塞; 之後,返回計算結果.
std::future<int> answer = std::async([] { std::stringstream stm; stm << "future id:" << std::this_thread::get_id() << std::endl; std::cout << stm.str(); int sum = 0; for (int i = 1; i <= 100; i++) { sum += i; std::cout << i << " "; } std::cout << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); // 增加延遲(1s) return sum; }); std::stringstream stm; stm << "main id:" << std::this_thread::get_id() << std::endl; std::cout << stm.str(); std::cout << "answer is: " << answer.get() << std::endl; // 此時會被阻塞, 直到異步任務返回 std::cout << "tag 2" << std::endl;
(2) std::async 允許通過添加額外的調用參數, 向函數傳遞額外的參數.
如果第一個參數是一個指向成員函數的指針, 第二個參數提供有這個函數成員類的具體對象(可以通過指針, 或者包裝在 std::ref 中), 剩余的參數可作為成員函數的參數傳入.
否則, 隨後的所有參數將作為函數的參數, 或作為指定可調用對象的第一個參數. 比如 std::thread, 當參數為右值(rvalues)時, 拷貝操作將使用移動的方式轉移原始數據. 這就允許使用“只移動”類型作為函數對象和參數.
class XFun { public: XFun() {} ~XFun() {} void f(const std::string& str) { std::stringstream stm; stm << "f called. " << this << "-->" << str << std::endl; std::cout << stm.str(); } std::string g(const std::string& str) { std::stringstream stm; stm << str << "[--> add by function g] " << this; return stm.str(); } //XFun& operator=(const XFun&) = delete; //XFun(const XFun&) = delete; void operator()(const std::string& str) { std::stringstream stm; stm << "operator() called. " << this << "-->" << str << std::endl; std::cout << stm.str(); } }; XFun x; std::cout << "addr of x:" << &x << std::endl; std::async(&XFun::f, &x, std::string("test f()")); std::future<std::string> f2 = std::async(&XFun::g, x, std::string("test g() temp")); // 創建一個 x 對象的副本傳入, 刪除賦值函數後, 將不能編譯 std::async(std::ref(x), std::string("test operator()")); std::async(XFun(), std::string("test operator() temp")); // 創建一個 XFun 的臨時對象傳入 std::cout << f2.get() << std::endl;
(3) 默認情況下, std::async 會啟動一個新線程來完成任務, 但是也可以指定額外的執行方式:
std::launch::defered 指定等到 wait 或 get 被調用時才執行.
std::launch::async 指定必須到獨立的線程中執行.
默認為: std::launch::defered | std::launch::async
auto f3 = std::async(std::launch::deferred, [] { std::stringstream stm; stm << "f3 called. TID:" << std::this_thread::get_id() << std::endl; std::cout << stm.str(); }); auto f4 = std::async(std::launch::async, [] { std::stringstream stm; stm << "f4 called. TID:" << std::this_thread::get_id() << std::endl; std::cout << stm.str(); }); std::stringstream stm; stm << "main. TID:" << std::this_thread::get_id() << std::endl; std::cout << stm.str(); std::this_thread::sleep_for(std::chrono::seconds(1)); f3.wait();