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