Skip to main content

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.