Flex threading w/ Web Workers

· Flex
Authors
One place where Flash falls short is threading.  Unfortunately it is not possible to create threads using the current version of the Flash Player. (10 point something something at the time of this writing)  What this means is if you have a large dataset you need to parse through, and you simply use an recursive function or iterator, the ActionScript Virtual Machine (AVM from now on) simply enters the loop and nothing else gets processed until this loop is done.  Where this becomes problematic is when it keeps the UI from redrawing.  If the UI becomes unresponsive for a non-trivial amount of time, the user can become frustrated and may stop using your app. Furthermore, if your script takes longer than the predefined (and not really overrideable) amount of time, Flash spits out an execution time limit exceeded error which kills code execution.  And nobody wants any code to be killed. So what we need is a work-around for no threads. In the recent past, there’s been a good deal of work trying to simulate threads in Flash.  Recently, most of this has been centered around a concept called greenthreading.  If you check out the blog of Charlie Hubbard you can get a pretty good sense of greenthreading and how to implement the idea within Flash.  For further insight, check out a blog post by Huyen Tue Dao on the subject. She recently gave a presentation at 360|Flex that did a good job of explaining.  For the lazy though, greenthreading is simply simulated threading using small functions that can be executed quickly. (I’ll call them units) A queue of these units is kept and, after deciding how many should be executed based on frame rate and thread priority, the units are processed one by one until either there are no more left, or the current time cycle is full.  At this point the queue essentially sleeps until the next time it’s allowed to start executing code.  It’s actually pretty smart and interesting stuff.  Most of the time this would suit the needs of someone trying to do background processing.  But what if I just want to process my data and not worry about these atomized functions. This is where HTML5 comes in. HTML5 offers a new concept called Web Workers. Web Workers are essentially thread-LIKE background scripts.  These scripts can run all night long without causing your main script to crash, freeze, melt, implode, explode, or otherwise stop working.  Each of these scripts is actually kept in a separate Javascript file. To create a new Worker in Javascript, you simply use a line like the following: 
1
var worker = new Worker('worker-script.js');
Generally, if you are farming some work out to a worker, you’ll want to get some response eventually.  Workers use a messaging structure based on DOM events.  A new message event has a data property that will hold the message you are trying to send.  This data property is supposed to take in a JSON-compatible object. (no function references or anything fancy like that)  I say supposed to because right now Safari only handles a string, which really cripples the idea of Web Workers.  To send a message to the worker simply add this: 
1
worker.postMessage("my message")
To handle the message inside the worker script add:
1
onmessage = function(ev) { var message = ev.data; }
To send a message from the worker script add:
1
self.postMessage("my response")
And finally, to handle that response on the outside use:
1
worker.onmessage = handleMessage;
Now, as mentioned the data property is supposed to take in a JSON object, but for now to make your code cross-browser compatible (I’m looking at you Safari!), I would suggest making your data a string [EDIT: As of June 7th 2010, Safari now supports complex objects in Web Workers]. If it were an object you could have a JSON object with topic and message properties. But you could make a string with the topic prepended and separated by a colon like so:
1
var message = "process-fibinacci: 1, 1, 2, 3, 5, 8, 13"
Then you would split the string on the colon with:
1
var topic = message.substr(0, message.indexOf(":"))
To get some more info on Web Workers, take a look at the proposed spec from WhatWG. It outlines use cases and messaging as well as SharedWorkers, Worker delegation, and more. The rest of the process simply uses ExternalInterface to communicate out to the Worker. The complete code is here.

Leave a Comment


*