| Package | flash.system | 
| Class | public final class Worker | 
| Inheritance | Worker  EventDispatcher  Object | 
| Language version: | ActionScript 3.0 | 
| Runtime version: | AIR 3.4 | 
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 both Android and 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:
setSharedProperty() 
       method and read a value using the getSharedProperty() method.createMessageChannel() 
       method.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.
See also
| Property | Defined by | ||
|---|---|---|---|
|  | constructor : 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 | ||
|  | prototype : Object [static]
	 A reference to the prototype object of a class or function object. | Object | |
| state : String [read-only]
    The current state of the worker in its lifecycle. | Worker | ||
| Method | Defined by | ||
|---|---|---|---|
| 
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
 
	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 | ||
|  | 
	Dispatches an event into the event flow. | EventDispatcher | |
| 
    Retrieves a value stored in this worker with a named key. | Worker | ||
|  | 
	Checks whether the EventDispatcher object has any listeners registered for a specific type 
	of event. | EventDispatcher | |
|  | 
	 Indicates whether an object has a specified property defined. | Object | |
|  | 
	 Indicates whether an instance of the Object class is in the prototype chain of the object specified 
	 as the parameter. | Object | |
|  | 
	 Indicates whether the specified property exists and is enumerable. | Object | |
| 
	Removes a listener from the EventDispatcher object. | Worker | ||
|  | 
     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 | ||
|  | 
	 Returns the string representation of this object, formatted according to locale-specific conventions. | Object | |
|  | 
	 Returns the string representation of the specified object. | Object | |
|  | 
	 Returns the primitive value of the specified object. | Object | |
|  | 
	Checks whether an event listener is registered with this EventDispatcher object or any of 
	its ancestors for the specified event type. | EventDispatcher | |
| Event | Summary | Defined by | ||
|---|---|---|---|---|
|  | [broadcast event] Dispatched when the Flash Player or AIR application gains operating system focus and becomes active. | EventDispatcher | ||
|  | [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 stateproperty changes. | Worker | |||
| current | property | 
current:Worker  [read-only]
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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 version: | 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 version: | 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.
    public static function get isSupported():Boolean
| state | property | 
state:String  [read-only]
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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
See also
| addEventListener | () | method | 
public override function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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.
JavaScript code in the AIR runtime uses this method to register
	event listeners for events defined by the AIR APIs. For other JavaScript events (such as the onload
	event of the DOM body object), you can use standard event handling techniques, as you would 
	for content running in the browser.
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)— This parameter applies to display objects in the
	ActionScript 3.0 display list architecture, used by SWF content.
	
	Determines whether the listener works in the capture phase or the 
	target and bubbling phases. IfuseCaptureis set totrue, 
	the listener processes the event only during the capture phase and not in the 
	target or bubbling phase. IfuseCaptureisfalse, the
	listener processes the event only during the target or bubbling phase. To listen for
	the event in all three phases, calladdEventListenertwice, once withuseCaptureset totrue, then again withuseCaptureset tofalse. | |
| 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  | 
| createMessageChannel | () | method | 
public function createMessageChannel(receiver:Worker):MessageChannel
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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);| receiver:Worker— The worker that will receive messages transmitted via 
                    the created message channel | 
| MessageChannel— 
                        The MessageChannel object created by the operation | 
| getSharedProperty | () | method | 
public function getSharedProperty(key:String):*
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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 | 
| *— The shared property value stored with the specified key, ornullif no value is stored for the specified key | 
| removeEventListener | () | method | 
public override function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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)— This parameter applies to display objects in the
	ActionScript 3.0 display list architecture, used by SWF content.
	
	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 toremoveEventListener()are required 
	to remove both, one call withuseCapture()set totrue, and another 
	call withuseCapture()set tofalse. | 
| setSharedProperty | () | method | 
public function setSharedProperty(key:String, value:*):void
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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:
shareable property set to trueIf 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. | 
See also
| start | () | method | 
public function start():void
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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 version: | AIR 3.4 | 
Stops this worker's code execution. Calling this method aborts any current ActionScript in the worker's swf.
Returns| Boolean—trueif code in the worker was running and 
    interrupted, orfalseif the worker was never started | 
| workerState | event | 
flash.events.Event
flash.events.Event.WORKER_STATE
| Language version: | ActionScript 3.0 | 
| Runtime version: | 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:
| Property | Value | 
|---|---|
| bubbles | false | 
| cancelable | false; there is no default behavior to cancel. | 
| currentTarget | The object that is actively processing the Event object with an event listener. | 
| target | The object that dispatched this event. | 
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;
        }
    }
}
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");
        }
    }
}
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;
    }
}
1. As dynamically loading a remote SWF that contains ActionScript code doesn't work, 
  the remote SWF has to be passed to worker as a stripped SWF.
  2. Embedding SWFs(having ABC code) using [Embed] tag will not work on iOS.
  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 two common ways to access the bytes of a SWF for this purpose on iOS:
  The first way is using Loader to load an external SWF file 
  and the second is using URLLoader to load SWF file.
The following example uses Loader API to load the SWF file.
package
{
    import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.MessageChannel;
	import flash.system.Worker;
	import flash.system.WorkerDomain;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	public class IOSWorkerExample extends Sprite
	{
		public var worker:Worker;
		public var bm:MessageChannel;
		public var mb:MessageChannel;
		public var tf:TextField;
		public var tfrmt:TextFormat;
		
		public function IOSWorkerExample()
		{
			super();
			
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			tf=new TextField();
			tfrmt= new TextFormat()
			tfrmt.size=80;
			tf.textColor = 0xFFFFF; 
			tf.defaultTextFormat=tfrmt;
		
			addChild(tf);		
			//creating the urlRequest object that references the background worker.
			var _urlRequest:URLRequest = new URLRequest("IOSBackWorker.swf");
			var _loader:Loader = new Loader();
			var _lc:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null);
			
			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
			_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
			_loader.load(_urlRequest, _lc);
			
		}
		// This function is called once the swf loading is completed
		public function completeHandler(e:Event):void
		{ 
			
			worker = WorkerDomain.current.createWorker(e.target.bytes);
			bm = worker.createMessageChannel(Worker.current);
			mb = Worker.current.createMessageChannel(worker);
			
			worker.setSharedProperty("btm", bm);
			worker.setSharedProperty("mtb", mb);
			//adding event handler on message receive from background
			bm.addEventListener(Event.CHANNEL_MESSAGE, onBackToMain);
			
			worker.start();  
			bm.receive(true);
			
		}
		
		public function errorHandler(e:IOErrorEvent):void
		{
			
			trace("In IO ErrorEvent Handler  "+e.text);
		}
		
		//This function is called when the main thread receives the message from the background worker.
		public function onBackToMain(event:Event):void
		{
			
			if(bm.messageAvailable)
			{
				// displaying the percentages based on the message received from the background.
				var progress:Number = bm.receive();
				trace("progress   "+progress);
				
				tf.text= progress.toString();
			}
		}
		
	}
}
Loader is called, we need to put isPrimordial 
  property check in background worker as shown in this example.
 
package
{
    import flash.display.Sprite;
	import flash.system.MessageChannel;
	import flash.system.Worker;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	
	public class IOSBackWorker extends Sprite
	{
		private var memory:ByteArray = new ByteArray();
		private var bm:MessageChannel;
		private var mb:MessageChannel;
		
		public function IOSBackWorker()
		{
			if(!Worker.current.isPrimordial)
			{
				memory.shareable = true;
				// creating objects of message channels
				bm = Worker.current.getSharedProperty("btm");
				mb = Worker.current.getSharedProperty("mtb");
				
				// calculating the percentage
				trace("message came");
				var j:Number =1;
				while (j<1000)
				{
					for(var i=0;i<100;i++){}
					var startTime=getTimer();
					// adding delay
					while (getTimer()-startTime <100);
					
					trace(j, (100*j)/1000);
					var progress:Number=(100*j)/1000;
					// sending the percentage to the main thread
					bm.send(progress);				
					
					j++;
				}			
			}
		}		
	}
}
