4

我在理解一些在线教程时遇到了一些麻烦,因此我在这里问。(使用 ActionScript 3、Adobe AIR 和 Flash Professional CS5.5)

我的 AS3 文档类中有一个非常繁重的函数,我需要异步运行,所以它不会停止 MovieClip 本身的代码(不要问我为什么,它只需要那样。)

那么,简单来说,如何异步运行这个文档类函数(StartNow)呢?代码可以放在文档类中,也可以放在movieclip上,我不在乎放在哪里。这似乎是一种相对简单和普遍的做法,但我所有的研究都没有挖掘出来。

谢谢!

4

2 回答 2

4

如果您的目标是 Flash 播放器 11.4,那么可以为 Worker 对象分配如此繁重的功能。我没有 FP11,最终制作了一个程序生成器,每次迭代总共持续超过 300 秒。我必须使用基于状态的方法,并与输入帧侦听器配对。在我的例子中,整个复杂的生成过程被分成足够小的逻辑块,可以在合理的时间跨度内完成,并且有一个变量跟踪当前的生成阶段。因此,当另一个帧调用生成函数时,它从该变量中读取最后完成的步骤,使用其数据集执行一个额外的步骤,存储新值并退出该帧。事实上,这不是一个纯粹的异步过程,而是一种伪多任务处理方法,如果使 SWF 滞后的函数是可拆分的,这可能适合您。

于 2012-11-22T07:30:50.510 回答
2

在 Flash 中没有异步运行函数这样的事情,你必须自己做,除非你想使用 Workers(就像 Vesper 说的那样)。Workers 为您提供了一个单独的流程。否则,您必须将计算分成几部分。这就是你的做法:

成像“跟踪”是一项非常繁重的操作。不是,只是为了说明。这个简单的 for 循环在帧上运行,并导致较低的帧速率,因为它都是在帧实际渲染之前计算的。

for(var i:int = 0; i < 1000; i ++)
{
   trace(i); // heavy calculation here
}

因此,您必须将计算分解为多个部分,并将其分解为能够随着时间的推移运行计算

为此,您必须创建一个每次只占用循环一部分的函数:

calculatePart(0, 1000, 20);

function calculatePart(startIndex:int, endIndex:int, amountPerRun:int)
{
    for(var i:int = startIndex; (i < startIndex + amountPerRun) || (i < endIndex); i ++)
    {
        trace(i); // heavy calculation here
    }
    if (i < endIndex)
    {
        calculatePart(i, endIndex, amountPerRun);
    }
}

这实际上与第一个代码中的简单 for 循环功能相同,它也输出 1000 个跟踪。它已准备好部分运行,但这还不是异步的。我们现在可以轻松地更改函数,因此函数会随着时间的推移而运行。我用setTimeout这个。您也可以为此使用ENTER_FRAME事件侦听器或Timer类,但为了这个示例,我尽量保持清晰。

calculatePart(0, 1000, 20, 100);

function calculatePart(startIndex:int, endIndex:int, amountPerRun:int, timeBeforeNextRun:Number)
{
    for(var i:int = startIndex; (i < startIndex + amountPerRun) && (i < endIndex); i ++)
    {
        trace(i); // heavy calculation here
    }
    if (i < endIndex)
    {
        setTimeout(calculatePart, timeBeforeNextRun, i, endIndex, amountPerRun, timeBeforeNextRun);
    }
}

如您所见,我添加了一个timeBeforeNextRun参数。如果您运行该示例,您可以看到输出 20 条跟踪需要 100 毫秒。

如果您将其设置得非常低,则计算将尝试非常快地完成,但是您当然不能通过尝试在更短的时间内完成更多操作来获得额外的速度。您必须使用时间和数量变量,您可以测试哪个变量实际上提供了更好的性能(或更少的延迟)。

 // more time between a run, less calculations per run
 calculatePart(0, 1000, 30, 10);

 // more calculations per run, more time between a run
 calculatePart(0, 1000, 100, 30);

希望这可以帮助。

如果您想使用更智能的时间计算,我发现这个实用程序类非常有用,它测量计算实际花费了多少时间,并改变时间本身。

于 2012-11-22T09:47:47.237 回答