Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading C++;17异步:运行一个this';方法阻塞整个对象_Multithreading_C++11_Asynchronous_Mutex_Stdasync - Fatal编程技术网

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,

我正在开发一个游戏。假设这些方法(以及其他一些方法)有一个对象加载状态:

  • 创造
  • 更新
  • 装载
每次CPU时钟滴答响时都会调用更新,而create只调用一次,它应该调用load函数(异步),以便加载一些游戏资源。在create函数内异步调用load允许(理论上)在create/load执行时从beling调用更新。然而,这并没有发生

在Visual Studio 2015之前,我是这样使用std::async的:

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:“没有其他方法可以在不存储未来的情况下使用异步吗?”。这就是我称之为“我怀孕了”的原因之一。