C++17 异步:运行 this' 方法阻塞了整个对象
C++17 async: running a this' method blocks the whole object
我正在开发一款游戏。假设有一个对象 LoadingState 具有这些方法(以及其他一些方法):
- 创建
- 更新
- 加载
每次 CPU 时钟滴答时都会调用更新,而创建只会调用一次,它应该调用加载函数(异步),以加载一些游戏资产。在 create 函数中异步调用 load 允许(理论上)在 create/load 执行时调用 beling 进行更新。然而,这并没有发生。
在 Visual Studio 2015 年之前,我是这样使用 std::async 的:
std::async(&LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
在迁移到 Visual Studio 2015 (C++17) 并阅读必须指定 std::launch 之后,否则可能会发生意外行为,异步现在这样调用:
std::async(std::launch::async, &LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
换句话说,在我看来 'this' 被 std::async 锁定,阻塞了整个对象,阻止了主线程调用更新。
更多相关代码:
void LoadingState::onCreate()
{
std::vector<std::string> assets;
assets.push_back("Images/Scenario/wall.png");
assets.push_back("Images/Scenario/bigdummy.png");
assets.push_back("Images/Scenario/buildings.png");
assets.push_back("Images/Scenario/floor.png");
assets.push_back("Images/Scenario/terrain.png");
assets.push_back("Images/Scenario/trees.png");
// Load assets asynchronously
std::async(std::launch::async, &LoadingState::load, this, assets);
}
void LoadingState::load(std::vector<std::string> assets)
{
unsigned int count = 0;
unsigned int ratio = 100U / assets.size();
// Cache the asset accordingly
for (auto& asset : assets)
{
// Load and store the asset
// ...
// Asset loaded
count++;
// Calculate the progress by count
m_progress = count * ratio;
}
// If assets were skipped or progress would be like 98% due to truncation, normalize it
m_progress = 100U;
}
void LoadingState::update(float delta)
{
// ...
// If finished loading the resources, move on to playing state!
if (m_progress >= 100U) {
m_machine->next(new PlayingState(m_machine));
}
}
我在这里误解了什么?!
PS:在迁移之前一切都习惯于 运行 顺利。
std::async(std::launch::async, &LoadingState::load, this, assets);
async
will block in its destructor until the async
function has finished 返回的 future
(不同于 每个其他 future
对象)。因此,您 必须 捕获 future
并使其保持活动状态(在必要时移动它),直到您准备好回答。
或者您可以停止使用 async
.
等设计不当的功能
reading that the std::launch has to be specified
不,不是。
我正在开发一款游戏。假设有一个对象 LoadingState 具有这些方法(以及其他一些方法):
- 创建
- 更新
- 加载
每次 CPU 时钟滴答时都会调用更新,而创建只会调用一次,它应该调用加载函数(异步),以加载一些游戏资产。在 create 函数中异步调用 load 允许(理论上)在 create/load 执行时调用 beling 进行更新。然而,这并没有发生。
在 Visual Studio 2015 年之前,我是这样使用 std::async 的:
std::async(&LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
在迁移到 Visual Studio 2015 (C++17) 并阅读必须指定 std::launch 之后,否则可能会发生意外行为,异步现在这样调用:
std::async(std::launch::async, &LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
换句话说,在我看来 'this' 被 std::async 锁定,阻塞了整个对象,阻止了主线程调用更新。
更多相关代码:
void LoadingState::onCreate()
{
std::vector<std::string> assets;
assets.push_back("Images/Scenario/wall.png");
assets.push_back("Images/Scenario/bigdummy.png");
assets.push_back("Images/Scenario/buildings.png");
assets.push_back("Images/Scenario/floor.png");
assets.push_back("Images/Scenario/terrain.png");
assets.push_back("Images/Scenario/trees.png");
// Load assets asynchronously
std::async(std::launch::async, &LoadingState::load, this, assets);
}
void LoadingState::load(std::vector<std::string> assets)
{
unsigned int count = 0;
unsigned int ratio = 100U / assets.size();
// Cache the asset accordingly
for (auto& asset : assets)
{
// Load and store the asset
// ...
// Asset loaded
count++;
// Calculate the progress by count
m_progress = count * ratio;
}
// If assets were skipped or progress would be like 98% due to truncation, normalize it
m_progress = 100U;
}
void LoadingState::update(float delta)
{
// ...
// If finished loading the resources, move on to playing state!
if (m_progress >= 100U) {
m_machine->next(new PlayingState(m_machine));
}
}
我在这里误解了什么?!
PS:在迁移之前一切都习惯于 运行 顺利。
std::async(std::launch::async, &LoadingState::load, this, assets);
async
will block in its destructor until the async
function has finished 返回的 future
(不同于 每个其他 future
对象)。因此,您 必须 捕获 future
并使其保持活动状态(在必要时移动它),直到您准备好回答。
或者您可以停止使用 async
.
reading that the std::launch has to be specified
不,不是。