ActionScript® 3.0 Reference for the Adobe® Flash® Platform
Home  |  Show Packages and Classes List |  Packages  |  Classes  |  What's New  |  Index  |  Appendixes
flash.system 

Worker  - AS3

Packageflash.system
Classpublic final class Worker
InheritanceWorker Inheritance EventDispatcher Inheritance Object

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

A Worker object represents a worker, which is a virtual instance of the Flash runtime. Each Worker instance controls and provides access to the lifecycle and shared data of a single worker.

A worker allows you to execute code "in the background" at the same time that other operations are running in another worker (including the main swf's worker). In a non-worker context some operations, for example processing a large set of data in a loop, take so long to execute that they prevent the main application thread from updating the screen quickly enough. This can cause stuttering or freezing the screen.

Using a worker allows you to perform a long-running or slow operation in the background. Each worker runs its code in a separate thread of execution from other workers. Long-running code in one worker does not block code in another worker from executing. Instead, the two sets of code run in parallel. Consequently, a worker can be used to execute code in the background while the main application thread stays free to continue updating the screen.

This capability of simultaneously executing multiple sets of code instructions is known as concurrency.

Note: The use of workers for concurrency is supported in both Flash Player and AIR on desktop platforms. For mobile platforms, concurrency is supported in AIR on Android but not in AIR on iOS. You can use the static isSupported property to check whether concurrency is supported before attempting to use it.

You do not create Worker instances directly by calling the Worker() constructor. In contexts where the use of workers for concurrency is supported, at startup the runtime automatically creates the Worker associated with the main SWF, known as the primordial worker.

Each additional worker is created from a separate swf. To create a new instance of the Worker class, pass a ByteArray with the bytes of the background worker's swf as an argument to the WorkerDomain class's createWorker()method. There are three common ways to access the bytes of a swf for this purpose:

  • Use the [Embed] metatag to embed the .swf file in the application as a ByteArray:

     // Embed the SWF file
     [Embed(source="../swfs/BgWorker.swf", mimeType="application/octet-stream")]
     private static var BgWorker_ByteClass:Class;
     
     private function createWorker():void
     {
       // create the background worker
       var workerBytes:ByteArray = new BgWorker_ByteClass();
       var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes);
       
       // 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();
     }
  • Load an external SWF file using a URLLoader:

     // load the SWF file
     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);
       
       // 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();
     }
  • Use a single swf as both the primordial worker and the background worker:

     // 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
       if (Worker.current.isPrimordial)    
       {
         // create a background worker
         var bgWorker:Worker = WorkerDomain.current.createWorker(swfBytes);
         
         // 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();
       }
       else // entry point for the background worker
       {
         // set up communication between workers using getSharedProperty()
         // ... (not shown)
         
         // start the background work
       }
     }

Workers execute in isolation from each other and do not have access to the same memory, variables, and code. However, there are three mechanisms available for passing messages and data between Worker instances:

  • Shared properties: Each worker has an internal set of named values that can be set and read both from within the worker itself as well as from other workers. You can set a value using the setSharedProperty() method and read a value using the getSharedProperty() method.
  • MessageChannel: A MessageChannel object allows you to send one-way messages and data from one worker to another. Code in the receiving worker can listen for an event to be notified when a message arrives. To create a MessageChannel object, use the createMessageChannel() method.
  • Shareable ByteArray: If a ByteArray object's shareable property is true, the same underlying memory is used for instances of that ByteArray in all workers. Because code in multiple workers can access the shared memory at the same time, your code should use the mechanisms described in the ByteArray.shareable property description to avoid problems from unexpected data changes.

Several runtime APIs are not available in code running in a background worker. These primarily consist of APIs related to user input and output mechanisms, or operating system elements like windows and dragging. As a rule, for any API that isn't supported in all contexts, use the isSupported, available, and similar properties to check whether the API is available in the background worker context before attempting to use the API.

Note: Native Extensions are not supported for background and secondary workers.

Workers are useful because they decrease the chances of the frame rate dropping due to the main rendering thread being blocked by other code. However, workers require additional system memory and CPU use, which can be costly to overall application performance. Because each worker uses its own instance of the runtime virtual machine, even the overhead of a trivial worker can be large. When using workers, test your code across all your target platforms to ensure that the demands on the system are not too large. Adobe recommends that you do not use more than one or two background workers in a typical scenario.

View the examples

More examples

Learn more

Related API Elements



Public Properties
 PropertyDefined By
 Inheritedconstructor : Object
A reference to the class object or constructor function for a given object instance.
Object
  current : Worker
[static] [read-only] Provides access to the worker that contains the current code
Worker
  isPrimordial : Boolean
[read-only] Indicates whether this worker is the primordial worker.
Worker
  isSupported : Boolean
[static] [read-only] Indicates whether the current runtime context supports the use of Worker objects for concurrent code execution.
Worker
  state : String
[read-only] The current state of the worker in its lifecycle.
Worker
Public Methods
 MethodDefined By
  
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
[override] Registers an event listener object with an EventDispatcher object so that the listener receives notification of an event.
Worker
  
Creates a new MessageChannel instance to send messages from the worker on which the method is called to another receiver worker.
Worker
 Inherited
Dispatches an event into the event flow.
EventDispatcher
  
Retrieves a value stored in this worker with a named key.
Worker
 Inherited
Checks whether the EventDispatcher object has any listeners registered for a specific type of event.
EventDispatcher
 Inherited
Indicates whether an object has a specified property defined.
Object
 Inherited
Indicates whether an instance of the Object class is in the prototype chain of the object specified as the parameter.
Object
 Inherited
Indicates whether the specified property exists and is enumerable.
Object
  
removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
[override] Removes a listener from the EventDispatcher object.
Worker
 Inherited
Sets the availability of a dynamic property for loop operations.
Object
  
Provides a named value that is available to code running in the worker's swf.
Worker
  
Starts the execution of the worker.
Worker
  
Stops this worker's code execution.
Worker
 Inherited
Returns the string representation of this object, formatted according to locale-specific conventions.
Object
 Inherited
Returns the string representation of the specified object.
Object
 Inherited
Returns the primitive value of the specified object.
Object
 Inherited
Checks whether an event listener is registered with this EventDispatcher object or any of its ancestors for the specified event type.
EventDispatcher
Events
 Event Summary Defined By
 Inherited[broadcast event] Dispatched when the Flash Player or AIR application gains operating system focus and becomes active.EventDispatcher
 Inherited[broadcast event] Dispatched when the Flash Player or AIR application operating loses system focus and is becoming inactive.EventDispatcher
  Dispatched when the value of the worker's state property changes.Worker
Property Detail

current

property
current:Worker  [read-only]

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Provides access to the worker that contains the current code



Implementation
    public static function get current():Worker

isPrimordial

property 
isPrimordial:Boolean  [read-only]

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Indicates whether this worker is the primordial worker.

The primordial worker is the worker in which the initial swf is running. This worker controls the rendering to the screen.

This property can be used to architect an application where the primordial worker and the background worker are two instances of the same swf file. The alternative is to structure your code so that the background worker uses different code compiled to a different swf from the primorial worker.



Implementation
    public function get isPrimordial():Boolean

isSupported

property 
isSupported:Boolean  [read-only]

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Indicates whether the current runtime context supports the use of Worker objects for concurrent code execution.

If concurrency is available, this property's value is true.



Implementation
    public static function get isSupported():Boolean

state

property 
state:String  [read-only]

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

The current state of the worker in its lifecycle. The possible values for this property are defined in the WorkerState class.



Implementation
    public function get state():String

Related API Elements

Method Detail

addEventListener

()method
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Registers an event listener object with an EventDispatcher object so that the listener receives notification of an event. You can register event listeners on all nodes in the display list for a specific type of event, phase, and priority.

After you successfully register an event listener, you cannot change its priority through additional calls to addEventListener(). To change a listener's priority, you must first call removeListener(). Then you can register the listener again with the new priority level.

Keep in mind that after the listener is registered, subsequent calls to addEventListener() with a different type or useCapture value result in the creation of a separate listener registration. For example, if you first register a listener with useCapture set to true, it listens only during the capture phase. If you call addEventListener() again using the same listener object, but with useCapture set to false, you have two separate listeners: one that listens during the capture phase and another that listens during the target and bubbling phases.

You cannot register an event listener for only the target phase or the bubbling phase. Those phases are coupled during registration because bubbling applies only to the ancestors of the target node.

If you no longer need an event listener, remove it by calling removeEventListener(), or memory problems could result. Event listeners are not automatically removed from memory because the garbage collector does not remove the listener as long as the dispatching object exists (unless the useWeakReference parameter is set to true).

Copying an EventDispatcher instance does not copy the event listeners attached to it. (If your newly created node needs an event listener, you must attach the listener after creating the node.) However, if you move an EventDispatcher instance, the event listeners attached to it move along with it.

If the event listener is being registered on a node while an event is being processed on this node, the event listener is not triggered during the current phase but can be triggered during a later phase in the event flow, such as the bubbling phase.

If an event listener is removed from a node while an event is being processed on the node, it is still triggered by the current actions. After it is removed, the event listener is never invoked again (unless registered again for future processing).

Parameters

type:String — The type of event.
 
listener:Function — The listener function that processes the event. This function must accept an Event object as its only parameter and must return nothing, as this example shows:
function(evt:Event):void

The function can have any name.

 
useCapture:Boolean (default = false)Determines whether the listener works in the capture phase or the target and bubbling phases. If useCapture is set to true, the listener processes the event only during the capture phase and not in the target or bubbling phase. If useCapture is false, the listener processes the event only during the target or bubbling phase. To listen for the event in all three phases, call addEventListener twice, once with useCapture set to true, then again with useCapture set to false.
 
priority:int (default = 0) — The priority level of the event listener. The priority is designated by a signed 32-bit integer. The higher the number, the higher the priority. All listeners with priority n are processed before listeners of priority n-1. If two or more listeners share the same priority, they are processed in the order in which they were added. The default priority is 0.
 
useWeakReference:Boolean (default = false) — Determines whether the reference to the listener is strong or weak. A strong reference (the default) prevents your listener from being garbage-collected. A weak reference does not.

Class-level member functions are not subject to garbage collection, so you can set useWeakReference to true for class-level member functions without subjecting them to garbage collection. If you set useWeakReference to true for a listener that is a nested inner function, the function will be garbage-collected and no longer persistent. If you create references to the inner function (save it in another variable) then it is not garbage-collected and stays persistent.

createMessageChannel

()method 
public function createMessageChannel(receiver:Worker):MessageChannel

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Creates a new MessageChannel instance to send messages from the worker on which the method is called to another receiver worker. Code in the worker that creates the MessageChannel object can use it to send one-way messages to the Worker object specified as the receiver argument.

Although a MessageChannel instance can be used to send messages and data from one Worker instance to another, at least one MessageChannel instance needs to be passed to a child Worker as a shared property by calling the Worker object's setSharedProperty() method.

    outgoingChannel = Worker.current.createMessageChannel(bgWorker);
    incomingChannel = bgWorker.createMessageChannel(Worker.current);
    
    bgWorker.setSharedProperty("incoming", outgoingChannel);
    bgWorker.setSharedProperty("outgoing", incomingChannel);
    
    // listen for messages from the receiving MessageChannel
    // This event is triggered when the background sends a message to this worker
    incomingChannel.addEventListener(Event.CHANNEL_MESSAGE, incomingMessageHandler);

Parameters

receiver:Worker — The worker that will receive messages transmitted via the created message channel

Returns
MessageChannel — The MessageChannel object created by the operation

getSharedProperty

()method 
public function getSharedProperty(key:String):*

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Retrieves a value stored in this worker with a named key.

Code in a child worker can call this method to retrieve a value as early as in the constructor of the worker swf's main class.

Parameters

key:String — The name of the shared property to retrieve

Returns
* — The shared property value stored with the specified key, or null if no value is stored for the specified key

removeEventListener

()method 
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Removes a listener from the EventDispatcher object. If there is no matching listener registered with the EventDispatcher object, a call to this method has no effect.

Parameters

type:String — The type of event.
 
listener:Function — The listener object to remove.
 
useCapture:Boolean (default = false)Specifies whether the listener was registered for the capture phase or the target and bubbling phases. If the listener was registered for both the capture phase and the target and bubbling phases, two calls to removeEventListener() are required to remove both, one call with useCapture() set to true, and another call with useCapture() set to false.

setSharedProperty

()method 
public function setSharedProperty(key:String, value:*):void

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Provides a named value that is available to code running in the worker's swf.

You can call this method before calling the worker's start() method. In that case the shared property is available to code in the worker's swf at construction time.

The value passed to the value parameter can be almost any object. Other than the exceptions noted below, any object that is passed to the value parameter is not passed by reference. Any changes made to the object in one worker after setSharedProperty() is called are not carried over to the other worker. The object is copied by serializing it to AMF3 format and deserializing it into a new object in the receiving worker. For this reason, any object that can't be serialized in AMF3 format, including display objects, can't be passed to the value parameter. In order for a custom class to be passed properly, the class definition must be registered using the flash.net.registerClassAlias() function or [RemoteClass] metadata. With either technique the same alias must be used for both worker's versions of the class.

There are five types of objects that are an exception to the rule that objects aren't shared between workers:

  • Worker
  • MessageChannel
  • shareable ByteArray (a ByteArray object with its shareable property set to true
  • Mutex
  • Condition

If you pass an instance of these objects to the value parameter, each worker has a reference to the same underlying object. Changes made to an instance in one worker are immediately available in other workers. In addition, if you pass the same instance of these objects more than once using setSharedProperty(), the runtime doesn't create a new copy of the object in the receiving worker. Instead, the same reference is re-used, reducing system memory use.

Calling this method with null or undefined for the value argument clears any previously-set value for the specified key argument. Cleaning up a value in this way removes the reference to it, allowing it to be garbage collected.

You can use any String value in the key argument. These shared properties are available to any code that has access to a worker. To avoid unintentionally overwriting a value, consider using a prefix, suffix, or similar mechanism to attempt to make your key names unique.

Parameters

key:String — The name under which the shared property is stored.
 
value:* — The value of the shared property.

Related API Elements

start

()method 
public function start():void

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Starts the execution of the worker. The runtime creates the worker thread and calls the constructor of the worker swf's main class.

This operation is asynchronous. Once the worker startup is complete, it changes its state property to WorkerState.RUNNING and dispatches a workerState event.

terminate

()method 
public function terminate():Boolean

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Stops this worker's code execution. Calling this method aborts any current ActionScript in the worker's swf.

Returns
Booleantrue if code in the worker was running and interrupted, or false if the worker was never started
Event Detail

workerState

Event
Event Object Type: flash.events.Event
property Event.type = flash.events.Event.WORKER_STATE

Language Version: ActionScript 3.0
Runtime Versions: Flash Player 11.4, AIR 3.4

Dispatched when the value of the worker's state property changes.

The Event.WORKER_STATE constant defines the value of the type property of a workerState event object.

This event has the following properties:

PropertyValue
bubblesfalse
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the Event object with an event listener.
targetThe object that dispatched this event.
WorkerExample.as

The following example demonstrates using a Worker object to perform a task in the background. It also shows communication between the parent worker and the background worker, including passing a custom class object between the workers.

This example consists of three ActionScript classes: WorkerExample is the main class and the parent worker. BackgroundWorker is the class that does the background work. It's compiled as the main class of the background worker swf. CountResult is a custom class that's used to pass data between the two workers as a single object rather than as multiple values.

In this example, the background worker counts in a loop up to a number specified by the parent worker. As it makes progress in its work it sends progress messages to the parent worker. Finally, when the count is finished the background worker sends a message to the parent worker notifying it that it finished and how long it took to count.

The WorkerExample class is the main class of the swf, so it is the main class of the primordial worker. In the initialize() method, the code creates the background worker object using the bytes of the BackgroundWorker class, which are embedded using an [Embed] tag.

After creating the background worker by calling WorkerDomain.createWorker(), the code sets up communication between the workers. First the code creates a set of MessageChannel objects. It passes them to the background worker by calling its setSharedProperty() method. Finally it registers for the background Worker object's workerState event and starts up the worker by calling its start() method.

As the background worker does its work, it sends progress (and eventually result) messages to the parent worker. The parent worker uses this information to update the progress bar and the text indicator.

package
{
    import com.adobe.example.vo.CountResult;
    
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.net.registerClassAlias;
    import flash.system.MessageChannel;
    import flash.system.Worker;
    import flash.system.WorkerDomain;
    import flash.system.WorkerState;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.text.TextFormatAlign;
    import flash.utils.ByteArray;
    
    public class WorkerExample extends Sprite
    {
        // ------- Embed the background worker swf as a ByteArray -------
        [Embed(source="../workerswfs/BackgroundWorker.swf", mimeType="application/octet-stream")]
        private static var BackgroundWorker_ByteClass:Class;
        public static function get BackgroundWorker():ByteArray
        {
            return new BackgroundWorker_ByteClass();
        }
        
        
        private var bgWorker:Worker;
        private var bgWorkerCommandChannel:MessageChannel;
        private var progressChannel:MessageChannel;
        private var resultChannel:MessageChannel;
        
        
        public function WorkerExample()
        {
            initialize();
        }
        
        
        private function initialize():void
        {
            // create the user interface
            setupStage();
            createStatusText();
            createProgressBar();
            
            // Register the alias so we can pass CountResult objects between workers
            registerClassAlias("com.adobe.test.vo.CountResult", CountResult);
            
            // Create the background worker
            bgWorker = WorkerDomain.current.createWorker(BackgroundWorker);
            
            // Set up the MessageChannels for communication between workers
            bgWorkerCommandChannel = Worker.current.createMessageChannel(bgWorker);
            bgWorker.setSharedProperty("incomingCommandChannel", bgWorkerCommandChannel);
            
            progressChannel = bgWorker.createMessageChannel(Worker.current);
            progressChannel.addEventListener(Event.CHANNEL_MESSAGE, handleProgressMessage)
            bgWorker.setSharedProperty("progressChannel", progressChannel);
            
            resultChannel = bgWorker.createMessageChannel(Worker.current);
            resultChannel.addEventListener(Event.CHANNEL_MESSAGE, handleResultMessage);
            bgWorker.setSharedProperty("resultChannel", resultChannel);
            
            // Start the worker
            bgWorker.addEventListener(Event.WORKER_STATE, handleBGWorkerStateChange);
            bgWorker.start();
        }
        
        
        private function handleBGWorkerStateChange(event:Event):void
        {
            if (bgWorker.state == WorkerState.RUNNING) 
            {
                _statusText.text = "Background worker started";
                bgWorkerCommandChannel.send(["startCount", 100000000]);
            }
        }
        
        
        private function handleProgressMessage(event:Event):void
        {
            var percentComplete:Number = progressChannel.receive();
            setPercentComplete(percentComplete);
            _statusText.text = Math.round(percentComplete).toString() + "% complete";
        }
        
        
        private function handleResultMessage(event:Event):void
        {
            var result:CountResult = resultChannel.receive() as CountResult;
            setPercentComplete(100);
            _statusText.text = "Counted to " + result.countTarget + " in " + (Math.round(result.countDurationSeconds * 10) / 10) + " seconds";
        }
        
        
        // ------- Create UI -------
        
        private var _currentPercentComplete:int = 0;
        private var _needsValidation:Boolean = false;
        private var _statusText:TextField;
        private var _progressBarRect:Shape;
        private var _progressBar:Shape;
        
        private function setupStage():void
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.stageWidth = 800;
            stage.stageHeight = 600;
            stage.color = 0xffffff;
        }
        
        
        private function createStatusText():void
        {
            _statusText = new TextField();
            _statusText.width = 400;
            _statusText.height = 25;
            _statusText.x = (stage.stageWidth - _statusText.width) / 2;
            _statusText.y = 150;
            
            var statusTextFormat:TextFormat = new TextFormat();
            statusTextFormat.color = 0xeeeeee;
            statusTextFormat.font = "Verdana";
            statusTextFormat.align = TextFormatAlign.CENTER;
            statusTextFormat.size = 16;
            _statusText.defaultTextFormat = statusTextFormat;
            _statusText.wordWrap = false;
            _statusText.opaqueBackground = 0x999999;
            _statusText.selectable = false;
            
            _statusText.text = "Initializing...";
            
            addChild(_statusText);
        }
        
        
        private function createProgressBar():void
        {
            _progressBarRect = new Shape();
            _progressBarRect.graphics.beginFill(0x000000, 0);
            _progressBarRect.graphics.lineStyle(2, 0x000000);
            _progressBarRect.graphics.drawRect(0, 0, 400, 30);
            _progressBarRect.graphics.endFill();
            
            _progressBarRect.x = (stage.stageWidth - _progressBarRect.width) / 2;
            _progressBarRect.y = 100;
            
            addChild(_progressBarRect);
            
            _progressBar = new Shape();
            _progressBar.graphics.beginFill(0x0000ee);
            _progressBar.graphics.drawRect(0, 0, 391, 21);
            _progressBar.x = _progressBarRect.x + 4;
            _progressBar.y = _progressBarRect.y + 4;
            
            addChild(_progressBar);
            
            _progressBar.scaleX = 0;
        }
        
        private function setPercentComplete(percentComplete:int):void
        {
            if (_currentPercentComplete == percentComplete)
                return;
            
            _currentPercentComplete = percentComplete;
            invalidateValue();
        }
        
        
        private function invalidateValue():void
        {
            if (_needsValidation)
                return;
            
            _needsValidation = true;
            addEventListener(Event.EXIT_FRAME, validate);
        }
        
        private function validate(event:Event):void
        {
            removeEventListener(Event.EXIT_FRAME, validate);
            _needsValidation = false;
            
            _redrawProgressBar();
        }
        
        private function _redrawProgressBar():void
        {
            _progressBar.scaleX = _currentPercentComplete / 100;
        }
    }
}
WorkerExample.BackgroundWorker.as

This class contains the code for the background worker. This class is compiled into its own swf file. That swf file is then embedded in the main swf.

In the initialize() method, it receives the MessageChannel objects that the parent worker passed in. They are used for communication between the two workers.

The parent worker calls the send() method on the commandChannel message channel to send a message. Inside the background worker, the runtime then dispatches the channelMessage event by calling the handleCommandMessage() method.

The background worker's actual work takes place in the count() method. As the background worker proceeds with its count, it sends progress messages to the parent worker by calling the send() method on the progressChannel MessageChannel object. When it finishes counting, it calls the send() method on the resultChannel MessageChannel object.

package com.adobe.example.workers
{
    import com.adobe.example.vo.CountResult;
    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.registerClassAlias;
    import flash.system.MessageChannel;
    import flash.system.Worker;
    import flash.utils.getTimer;
    
    public class BackgroundWorker extends Sprite
    {
        private var commandChannel:MessageChannel;
        private var progressChannel:MessageChannel;
        private var resultChannel:MessageChannel;
        
        
        public function BackgroundWorker()
        {
            initialize();
        }
        
        
        private function initialize():void
        {
            registerClassAlias("com.adobe.test.vo.CountResult", CountResult);
            
            // Get the MessageChannel objects to use for communicating between workers
            // This one is for receiving messages from the parent worker
            commandChannel = Worker.current.getSharedProperty("incomingCommandChannel") as MessageChannel;
            commandChannel.addEventListener(Event.CHANNEL_MESSAGE, handleCommandMessage);
            // These are for sending messages to the parent worker
            progressChannel = Worker.current.getSharedProperty("progressChannel") as MessageChannel;
            resultChannel = Worker.current.getSharedProperty("resultChannel") as MessageChannel;
        }        
        
        
        private function handleCommandMessage(event:Event):void
        {
            if (!commandChannel.messageAvailable)
                return;
            
            var message:Array = commandChannel.receive() as Array;
            
            if (message != null && message[0] == "startCount")
            {
                count(uint(message[1]));
            }
        }
        
        
        private function count(targetValue:uint):void
        {
            var startTime:int = getTimer();
            var onePercent:uint = uint(Math.ceil(targetValue / 100));
            var oneHalfPercent:Number = onePercent / 2;
            
            var i:uint = 0;
            while (i < targetValue)
            {
                i++;
                // only send progress messages every one-half-percent milestone
                // to avoid flooding the message channel
                if (i % oneHalfPercent == 0)
                {
                    progressChannel.send(i / onePercent);
                }
            }
            
            var elapsedTime:int = getTimer() - startTime;
            var result:CountResult = new CountResult(targetValue, elapsedTime / 1000);
            resultChannel.send(result);
            
            trace("counted to", targetValue.toString(), "in", elapsedTime, "milliseconds");
        }
    }
}
WorkerExample.CountResult.as

This class defines the CountResult value object. This is a custom class that is passed between the two workers. In order to pass a custom class between the workers, each worker calls the registerClassAlias() method, using the same alias name.
package com.adobe.example.vo
{
    public class CountResult
    {
        public function CountResult(countTarget:uint=0, countTime:Number=0)
        {
            this.countTarget = countTarget;
            this.countDurationSeconds = countTime;
        }
        
        public var countTarget:uint;
        public var countDurationSeconds:Number;
    }
}