Question

I'm having a bit of trouble making sense of some of the tutorials for this online, thus why I'm asking here. (Using ActionScript 3, Adobe AIR, and Flash Professional CS5.5)

I have a very heavy function in my AS3 document class that I need to run asynchronously, so it doesn't stop the code on the MovieClip itself (don't ask me why, it just needs to be that way.)

So, simply put, how do I run this document class function (StartNow) asynchronously? The code can be placed in the document class or on the movieclip, I don't care where. It seems to be a relatively simple and common practice, but all my research is digging up nothing.

Thanks!

Was it helpful?

Solution 2

In Flash there is no such thing as run a function asynchronously, you have to do it yourself, unless you want to use Workers (like Vesper said). Workers gives you a separate process. Otherwise, you have to break your calculation into parts. This is how you do it:

Imaging 'trace' is a very heavy operation. It's not, but just to illustrate. This simple for-loop is runned on a frame, and causes a lower framerate, since it's all calculated before the frame actually renders.

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

So you have to break the calculation into parts, and break it to be able to run the calculation over time.

To do that, you have to create a function which just takes a part of the loop every time:

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);
    }
}

This is actually the same function as the simple for-loop in the first code, it also outputs 1000 traces. It is prepared to run in parts, but this isn't async yet. We can now change the function easily, so the function operates over time. I use the setTimeout for this. You can also use a ENTER_FRAME event-listener or the Timer class for this, but for the sake of this example I try to keep it clear.

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);
    }
}

As you can see, I've added a timeBeforeNextRun parameter. If you run the example, you can see it takes 100 milliseconds before 20 traces are outputted.

If you set it very low, the calculation will be tried to be done very fast, however you cannot gain extra speed just by trying to do more in less time of course. You have to play with the time and amount variables, you can test which one actually gives better performance (or less lag).

 // 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);

Hope this helps.

If you want to use a smarter calculation of the time, I found this utility class very helpful, which measures how much time the calculation actually took, and alter the time itself.

OTHER TIPS

If your target is Flash player 11.4, there are Worker objects which can be assigned such a heavy function. I had no FP11, and eventually made a procedural generator that lasted more than 300 seconds per iteration in total. I had to use a state-based approach, paired with an enter frame listener. In my c ase, the entire complex generation process was split into logical chunks that were small enough to be completed within a reasonable timespan, and had a variable tracking the current generation phase. So, when another frame called the generation function, it read last completed step from that variable, performed one extra step with its set of data, stored the new value and exited for the frame. This, as is, is not a pure asynchronous process, but a pseudo-multitasking approach, this can suit you if your function that makes your SWF lag is splittable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top