Multithreading C++;17异步:运行一个this';方法阻塞整个对象
我正在开发一个游戏。假设这些方法(以及其他一些方法)有一个对象加载状态:Multithreading C++;17异步:运行一个this';方法阻塞整个对象,multithreading,c++11,asynchronous,mutex,stdasync,Multithreading,C++11,Asynchronous,Mutex,Stdasync,我正在开发一个游戏。假设这些方法(以及其他一些方法)有一个对象加载状态: 创造 更新 装载 每次CPU时钟滴答响时都会调用更新,而create只调用一次,它应该调用load函数(异步),以便加载一些游戏资源。在create函数内异步调用load允许(理论上)在create/load执行时从beling调用更新。然而,这并没有发生 在Visual Studio 2015之前,我是这样使用std::async的: std::async(&LoadingState::load, this,
- 创造
- 更新
- 装载
std::async(&LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
std::async(std::launch::async, &LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
迁移到Visual Studio 2015(C++17)并读取到必须指定std::launch,否则可能会发生意外行为后,异步现在被称为:
std::async(&LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
std::async(std::launch::async, &LoadingState::load, this, THE_ASSETS_PATHS_STRING_VECTOR);
换句话说,在我看来,“this”被std::async锁定,阻塞了整个对象,阻止了主线程调用update
更相关的代码:
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));
}
}
void LoadingState::onCreate()
{
std::载体资产;
资产。推回(“Images/Scenario/wall.png”);
资产。推回(“Images/Scenario/bigsdummy.png”);
资产。推回(“image/Scenario/buildings.png”);
资产。推回(“Images/Scenario/floor.png”);
资产。推回(“Images/Scenario/terrain.png”);
资产。推回(“Images/Scenario/trees.png”);
//异步加载资产
std::async(std::launch::async,&LoadingState::load,this,assets);
}
无效加载状态::加载(标准::向量资源)
{
无符号整数计数=0;
无符号整数比率=100U/assets.size();
//相应地缓存资产
用于(自动和资产:资产)
{
//加载并存储资产
// ...
//装载资产
计数++;
//按计数计算进度
m_进度=计数*比率;
}
//如果跳过了资产,或者由于截断,进度将达到98%,请将其正常化
m_进度=100U;
}
无效加载状态::更新(浮动增量)
{
// ...
//如果资源加载完毕,请转到播放状态!
如果(m_进度>=100U){
m_机器->下一步(新播放状态(m_机器));
}
}
我在这里误解了什么
PS:在迁移之前,一切都运行得很平稳
由async
返回的future
(与其他所有future
对象不同)。因此,您必须捕获该未来
,并使其保持活动状态(在必要时移动它),直到您准备好回答为止
或者您可以停止使用诸如async
之类的功能
读取必须指定的std::launch
不,没有
由async
返回的future
(与其他所有future
对象不同)。因此,您必须捕获该未来
,并使其保持活动状态(在必要时移动它),直到您准备好回答为止
或者您可以停止使用诸如async
之类的功能
读取必须指定的std::launch
不,它没有。先说说C++11,我保证您没有使用
std::async
!资源路径字符串向量也不存在。您的批评/讽刺没有帮助。“Visual Studio 2015(C++17)”VS 2015不包含C++17。它最多包含C++17位。除非捕获由std::async
返回的std::future
,否则它将始终被阻止。@yvesherri实际上,我错了。标准不要求它阻止,但它可能会阻止。请参阅N4296中的30.6.8.5[futures.async]。在使用C++11之前,我保证您没有使用std::async
!资源路径字符串向量也不存在。您的批评/讽刺没有帮助。“Visual Studio 2015(C++17)”VS 2015不包含C++17。它最多包含C++17位。除非捕获由std::async
返回的std::future
,否则它将始终被阻止。@yvesherri实际上,我错了。标准不要求它阻止,但它可能会阻止。请参阅N4296中的30.6.8.5[futures.async]。async
并非构思不周。只是没有给出适当的默认值。C++14修复了这个问题。您断章取义地引用了OP:“必须指定std::launch,否则可能会发生意外行为。”这在C++14中是正确的。“如果std::launch::async或std::launch::deferred都未在策略中设置任何实现定义的策略标志,则该行为未定义。”-@yvesherri:调用第一个重载将调用第二个重载,提供这两个参数。这不是未定义的行为;通过函数重载,这只是一个默认参数。无论如何,没有其他方法可以使用异步而不存储未来?如果我不直接处理它,而不是让异步异步运行,那么保留它似乎很奇怪。@Yvesherri:“没有其他方法可以在不存储未来的情况下使用异步吗?”。这就是我称之为“il构思”的一个原因。async
并非构思不周。只是没有给出适当的默认值。C++14修复了这个问题。您断章取义地引用了OP:“必须指定std::launch,否则可能会发生意外行为。”这在C++14中是正确的。“如果std::launch::async或std::launch::deferred都未在策略中设置任何实现定义的策略标志,则该行为未定义。”-@yvesherri:调用第一个重载将调用第二个重载,提供这两个参数。这不是未定义的行为;通过函数重载,这只是一个默认参数。无论如何,没有其他方法可以使用异步而不存储未来?如果我不直接处理它,而不是让异步异步运行,那么保留它似乎很奇怪。@Yvesherri:“没有其他方法可以在不存储未来的情况下使用异步吗?”。这就是我称之为“我怀孕了”的原因之一。