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;
}

  

posted @ 2022-05-28 15:31  strive-sun  阅读(85)  评论(0编辑  收藏  举报