C++ 多執行緒的錯誤和如何避免(11)
阿新 • • 發佈:2022-05-28
不要在對時間敏感的上下文中使用 .get()
先看下面的程式碼,
#include "stdafx.h" #include <future> #include <iostream> int main() { std::future<int> myFuture = std::async(std::launch::async, []() { std::this_thread::sleep_for(std::chrono::seconds(10)); return 8; }); // Update Loop for rendering data while (true) { // Render some info on the screen std::cout << "Rendering Data" << std::endl; int val = myFuture.get(); // this blocks for 10 seconds // Do some processing with Val } return 0; }
示例顯示主執行緒在等待 std::async 返回的結果,但是 while 迴圈將被阻塞,直到非同步任務完成(在這種情況下為 10 秒)。如果將此視為在螢幕上呈現資料的迴圈,則可能會導致非常糟糕的使用者體驗。
另外還需要注意的是,它試圖在沒有共享狀態的情況下第二次呼叫 .get(),這樣會導致程式崩潰,因為 future 結果已經在第一次迴圈時檢索了。
解決方案是在呼叫 .get() 之前檢查 myFuture 是否有效,這樣既不會阻塞非同步作業的完成,也不會嘗試輪詢已經檢索的值。
#include "stdafx.h" #include <future> #include <iostream> int main() { std::future<int> myFuture = std::async(std::launch::async, []() { std::this_thread::sleep_for(std::chrono::seconds(10)); return 8; }); // Update Loop for rendering data while (true) { // Render some info on the screen std::cout << "Rendering Data" << std::endl; if (myFuture.valid()){ int val = myFuture.get(); // this blocks for 10 seconds // Do some processing with Val } } return 0; }