0

如果未加载来自服务器的某些内容,我试图阻止进入场景,我有标志 bool

    done = false;
    CCHttpRequest *pRequest;
    // initialization ....
        pRequest->setResponseCallback(this, httpresponse_selector(SceneController::on_response));

        CCHttpClient::getInstance()->send(pRequest);
        pRequest->release();

while(!done) {
        std::chrono::milliseconds duration(1);
        std::this_thread::sleep_for(duration);
}

on_response在我设置的函数回调中

done = true;

什么应该(但不起作用)打破无限循环。这种方法的问题是永远不会调用回调(永远不会到达回调中第一行的断点)。当我评论while loop它称为回调。

有谁知道什么是问题以及如何防止进一步执行,直到我从服务器获取数据?

当它在回调内的断点上工作时调用堆栈

在此处输入图像描述

4

2 回答 2

0

Callback is NOT another thread as you might be thinking. You trying hold current function execution 'till callback gets called'. That's not correct. You should return from it and allow callback to be called. This should do:

done = false;
CCHttpRequest *pRequest;
// initialization ....
pRequest->setResponseCallback(this, httpresponse_selector(SceneController::on_response));
CCHttpClient::getInstance()->send(pRequest);        
pRequest->release();

if (!done) 
{
    return;
}
else
{
    // Do here whatever you want to do after callback changes flag
}
于 2015-01-30T15:07:54.400 回答
0

您所有的代码都将在 Cocos 线程中执行,CCHttpRequest 有自己的线程从服务器获取数据,然后当所有数据被获取时,您之前注册的回调也会在 Cocos 线程中调用。

注册回调后,cocos线程继续执行到你的while,现在回调没有被调用(数据没有完成)你while将永远运行。数据完成后,需要在 cocos 线程中执行回调,但您会看到while一直阻塞它。

在异步世界中(请参阅此处和此处,您必须了解异步),您不能使用您正在使用的模式“阻止进一步执行,直到您从服务器获取数据”。尝试通过您的done变量在您不希望它执行的地方阻止它。

例如:

done = false;
CCHttpRequest *pRequest;
// initialization ....
pRequest->setResponseCallback(this, httpresponse_selector(SceneController::on_response));

CCHttpClient::getInstance()->send(pRequest);
pRequest->release();

然后在任何你不希望用户与你的游戏界面交互的地方,比如在 Touch 中:

void onTouchBegan(Event *pEvent, Touch *pTouch)
{
  if (!done)
  {
    return false;
  }

  // code when `done == true`
}

void onTouchEnded(Event *pEvent, Touch *pTouch)
{
  // Code here will not be executed if `onTouchBegan` return `false`
}

每当 onTouchBegan返回 false 时,将不再执行触摸代码,然后阻止您的用户与游戏元素进行交互。另外为了防止按钮菜单点击,将禁用设置为其父菜单容器:menu->setEnabled(false)然后在获取完成时设置回启用。

于 2015-01-31T03:14:18.760 回答