【发布时间】:2016-11-17 19:25:26
【问题描述】:
我正在开发一款游戏。假设有一个对象 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:在迁移之前,所有东西都可以顺利运行。
【问题讨论】:
-
在 C++11 之前,我向你保证你没有使用
std::async! -
THE_ASSETS_PATHS_STRING_VECTOR 也不存在。你的批评/讽刺没有帮助。
-
"Visual Studio 2015 (C++17)" VS 2015 不包含 C++17。它包含最多的C++17位。
-
除非你捕捉到
std::async返回的std::future,否则它将总是阻塞。 -
@YvesHenri 实际上,我弄错了。该标准不要求它阻止,但它可能。请参阅 N4296 中的 30.6.8.5 [futures.async]。
标签: multithreading c++11 asynchronous mutex stdasync