views:

3389

answers:

6

Is it possible to call a function asynchronously in Flex? I want to parse a file at regular intervals without blocking the rest of the application, what is the recommended approach for this?

+12  A: 

Actionscript doesn't support multithreading, which I think is what you are really asking about here.

While the functionality isn't inherent in actionscript (or Flex) you could set up a mock system using events and timers.

I'm a little unclear on your exact question, so I'll give two answers:

1) You want to process a file every few seconds to act on any changes.

In this case all you need to do is set up a timer to check the file periodically:

var fileTimer:Timer = new Timer(5000);
fileTimer.addEventListener(TimerEvent.TIMER, checkFile);

...

private function checkFile(event:TimerEvent):void {
  // read the file and do whatever you need to do.
}

2) You want to parse a very large file but don't want the application to hang whilst doing it.

If you want to process the file in the background, while keeping the main application responsive then I would probably create a function that would parse several lines of the file and then send an event and return. Listen for the event and start a timer that would wait a few milliseconds before calling the function again to parse the next set of lines.

This would break up the parsing of a large file with enough down time to keep the rest of your app running smoothly. You'd have to play with the timer interval and number of lines to parse at once to strike a good balance of responsiveness and the time needed to parse the file.

Hope that makes sense!

Matt Guest
Flash Player will not render while ActionScript is running. validateNow() will force a Flex component to draw, but it does not actually render to the screen until all the ActionScript in a frame is finished running.
joshtynjala
You are absolutely correct, I've removed the erroneous code from my answer so that nobody attempts to use it.
Matt Guest
+3  A: 

The simplest answer is to use the callLater routine - see some documentation here.

callLater( parseFile, [filename] );

...

public function parseFile( filename : String ) : void
{
    // parse the file
}

Another approach is to use the setTimeout call, defined in the flash.utils package. This one lets you call a routine after a specified amount of time has passed. Using this routine, you could set up your parseFile function to call itself repeatedly, giving you the regular intervals you were looking for:

parseFile( filename );

...

public function parseFile( filename : String ) : void
{
    // parse the file

    // call this function again in 5 seconds
    setTimeout( parseFile, 5000, filename );
}
Matt Dillard
A: 

There is also a setInterval function which will call a function at regular intervals which could be useful.

igkuk7
+2  A: 

Interestingly, just yesterday I described a solution to this problem in response to a different question.

erikprice
+2  A: 

setTimeout and setInterval are both deprecated.

The Timer class not only allows a delay, but also a repeatCount: how many times it will throw a TIMER event and start counting down again. Presumably, one would call myTimer.stop() inside the event before doing whatever you wanted to do, and myTimer.start() when one was done.

private function newLinesToParse() : void
{
    myTimer = new Timer(30000, 9999);
    myTimer.addEventListener(Timer.TIMER, myTimerTick);
    myTimer.start(); 
}

private function myTimerTick(event : Event) : void
{
    myTimer.stop();    // or (event.currentTarget as Timer).stop();

    // do a few lines

    if (anyMoreLines)  
        myTimer.start();
    else
        myTimer = null;
}

Cheers

Richard Haven
+1  A: 

What you need is a concept called Green threads. There is a green threading lib out there, but I have not used it.

The implementation I did for an import process (1 - 5 minutes) actually tracked how long the executions were taking and allowed for a configurable amount of time per cycle. This allows you to choose the number of frames you dropped (we were simply updating a modal progress bar). I also subclassed it with a version that ran through a ICollectionView with a IViewCursor and fired off the event with each item.

I cannot supply the source code due to it's connection with a commercial product, but the concept is quite simple to implement.

Richard Szalay