1. 程式人生 > 其它 >C++ 多執行緒的錯誤和如何避免(11)

C++ 多執行緒的錯誤和如何避免(11)

不要在對時間敏感的上下文中使用 .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; }