Creating and managing workers
The first step in using a worker for concurrency is to create a background worker. You use two types of objects to create a worker. First is a Worker instance, which is what you create. The other is a WorkerDomain object, which creates the Worker and manages the running Worker objects in an application.
When the runtime loads, it automatically creates the WorkerDomain object. The runtime also automatically creates a worker for the main swf of the application. This first worker is known as the primordial worker .
Because there is only one WorkerDomain object for an application, you access the
WorkerDomain instance using the static WorkerDomain.current
property.
At any time, you can access the current Worker instance (the worker in which the
current code is running) using the static Worker.current
property.
Creating a Worker object from a swf
Just as the main swf runs within the primordial worker, a background worker
executes the code of a single swf file. To use a background worker, you must
author and compile the worker's code as a swf file. To create the background
worker, the parent worker needs access to that swf file's bytes as a ByteArray
object. You pass that ByteArray to the WorkerDomain object's createWorker()
method to actually create the worker.
There are three main ways to get the background worker swf as a ByteArray object:
Embedding the worker swf
Use the [Embed] metatag to embed the worker swf into the main swf as a ByteArray:
[Embed(source="../swfs/BgWorker.swf", mimeType="application/octet-stream")]
private static var BgWorker_ByteClass:Class;
private function createWorker():void
{
var workerBytes:ByteArray = new BgWorker_ByteClass();
var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes);
// ... set up worker communication and start the worker
}
The worker swf is compiled into the main swf as a ByteArray subclass named BgWorker_ByteClass. Creating an instance of that class gives you a ByteArray pre-populated with the worker swf's bytes.
Loading an external worker swf
Use a URLLoader object to load an external swf file. The swf file must come from the same security domain, such as a swf file loaded from the same internet domain as the main swf or included in an AIR application package.
var workerLoader:URLLoader = new URLLoader();
workerLoader.dataFormat = URLLoaderDataFormat.BINARY;
workerLoader.addEventListener(Event.COMPLETE, loadComplete);
workerLoader.load(new URLRequest("BgWorker.swf"));
private function loadComplete(event:Event):void
{
// create the background worker
var workerBytes:ByteArray = event.target.data as ByteArray;
var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes);
// ... set up worker communication and start the worker
}
When the URLLoader finishes loading the swf file, the swf's bytes are available
in the URLLoader object's data
property ( event.target.data
in the example).
Using the main swf as the worker swf
You can use a single swf as both the main swf and the worker swf. Use the main
display class's loaderInfo.bytes
property to access the swf's bytes.
// The primordial worker's main class constructor
public function PrimordialWorkerClass()
{
init();
}
private function init():void
{
var swfBytes:ByteArray = this.loaderInfo.bytes;
// Check to see if this is the primordial worker or the background worker
if (Worker.current.isPrimordial)
{
// create a background worker
var bgWorker:Worker = WorkerDomain.current.createWorker(swfBytes);
// ... set up worker communication and start the worker
}
else // entry point for the background worker
{
// set up communication between workers using getSharedProperty()
// ... (not shown)
// start the background work
}
}
If you use this technique, use an if
statement to branch the swf file code
within the main class's constructor or a method it calls. To determine whether
the code is running in the main worker or the background worker, check the
current Worker object's isPrimordial
property, as shown in the example.
Starting a worker's execution
Once you have created a worker, you start its code executing by calling the
Worker object's start()
method. The start()
operation doesn't happen
immediately. To know when the worker is running, register a listener for the
Worker object's workerState
event. That event is dispatched when the Worker
object switches states in its lifecycle, such as when it starts executing code.
In your workerState
event handler, check that the Worker object's state
property is WorkerState.RUNNING
. At that point the worker is running and its
main class's constructor has run. The following code listing shows an example of
registering for the workerState
event and calling the start()
method:
// listen for worker state changes to know when the worker is running
bgWorker.addEventListener(Event.WORKER_STATE, workerStateHandler);
// set up communication between workers using
// setSharedProperty(), createMessageChannel(), etc.
// ... (not shown)
bgWorker.start();
private function workerStateHandler(event:Event):void
{
if (bgWorker.state == WorkerState.RUNNING)
{
// The worker is running.
// Send it a message or wait for a response.
}
}
Managing worker execution
At any time you can access the set of running workers in your application using
the WorkerDomain class's listWorkers()
method. This method returns the set of
workers whose state
property is WorkerState.RUNNING
, including the
primordial worker. If a worker hasn't been started or if its execution has
already been stopped, it is not included.
If you no longer need a worker, you can call the Worker object's terminate()
method to shut down the worker and release its memory and other system
resources.