在我的空中程序中,我写了一个这样的函数:
public function getDataFromXml():void
{
for each()
{.....} //here may contain thounds of fields and name
}
当然,这个功能可能需要10s-20s,所以我想添加一个进度条,然后出现问题,进度条被阻塞了。我发现一帧大约需要40ms,所以原因一定是在间隔执行程序帧数,怎么解决?
在我的空中程序中,我写了一个这样的函数:
public function getDataFromXml():void
{
for each()
{.....} //here may contain thounds of fields and name
}
当然,这个功能可能需要10s-20s,所以我想添加一个进度条,然后出现问题,进度条被阻塞了。我发现一帧大约需要40ms,所以原因一定是在间隔执行程序帧数,怎么解决?
这个想法是监视循环中花费的时间,如果此时间超过一帧的允许时间,则等待下一帧。
private var _dummy:Sprite = new Sprite();
private var _data:Array;
public function getDataFromXml():void
{
var startTime:Number = getTimer();
const allowedTime:Number = 1000 / stage.frameRate;
while (getTimer() - startTime < allowedTime && _data.length > 0)
{
_data.pop(); //pop your data to remove the treated lines, or keep track of the current index
//do your treatment here
}
if (_data.length == 0)
{
//the end
}
else
{
//wait for the next frame to go on
_dummy.addEventListener(Event.ENTER_FRAME, onNextFrame);
}
}
private function onNextFrame(event:Event):void
{
_dummy.removeEventListener(Event.ENTER_FRAME, onNextFrame);
getDataFromXml();
}
您的问题的主要原因是尽可能多的 Flash 试图遵循它所要求的帧速度,它必须在一帧中完成所有脚本执行,然后才能进入下一帧。因此,如果您的 foreach 需要 40 秒来执行,那么 Flash 将无法传递到下一帧,直到达到 40 秒。
这个问题的主要解决方案是:你必须使这个执行异步。有几种方法可以做到这一点。
第一种方法是把你的执行分成更小的部分。由于您使用循环,因此可以通过限制循环在一帧中执行的步骤数来非常容易。基本上,它可能看起来像这样:
private var _getDataIndex:Number;
private var _extractedData:Array;
public function getDataFromXml():void
{
_getDataIndex = 0;
_extractedData = new Array();
this.addEventListener(Event.ENTER_FRAME, getDataFromXmlStep); // You can also use a Timer instead
for each()
{.....} //here may contain thounds of fields and name
}
private function getDataFromXmlStep(evt:Event):void
{
for(var i:int = 0; i < 5; i++) {
var field:XML = _myXMLData[_getDataIndex];
if (field == null) {
getDataFromXmlFinished()
break;
}
{.....} // your code for the field, the result saved in _extractedData
_getDataIndex++;
}
}
private function getDataFromXmlFinished():void {
this.removeEventListener(Event.ENTER_FRAME, getDataFromXmlStep); // You can also use a Timer instead
// extraction finished
}
如果您使用 AIR 3.4 或更高版本,另一种解决方案是使用Worker。简而言之,您将工作委托给另一个线程,该线程不显示任何内容,并且可以在主代码执行其他操作(管理与窗口的交互)时自主转动。Worker 是一件值得学习的好东西,但其局限性在于您需要最新版本的 AIR 才能让他们工作。