Before we start, let's cover two simple notions. In this article, we will refer to the UI worker (the one you always worked with in the past) as the primordial worker. It is still the entry point of your app, the primordial worker is never created by user code and is created automatically by the runtime, it is essentially your good old document class, extendingSprite at least.
So to create your child worker from the primordial worker, you will just write:
1.var worker:Worker = WorkerDomain.current.createWorker(Workers.EncoderWorker);
As you can see, the Worker is created through the help of the WorkerDomain object, that you can see as a factory. One and only WorkerDomain object exists for the entire runtime, and cannot be constructed by user code. Workers.EncoderWorker points here to our embedded worker using the [Embed tag].
At this point, our background logic is not executed, to trigger this, we simply use the start() API:
Now, the code you would have in the constructor in your background worker is started and waiting for the action. The Worker class has a state instance property to allow you to check at any time which state is your worker in. The different states are available through constants of the WorkerState class: NEW, RUNNING, TERMINATED
You could create as many workers was you want, but keep in mind that it is costly to create tons of them, each Worker is in fact a constrained virtual Flash Player instance, so it has a cost in memory (5-7mb). Ok, so now we need to communicate between workers. For this, please welcome the MessageChannel API. To communicate and send a message from a worker to another, you would create such a message channel like this:
1.var mainToBack:MessageChannel = Worker.current.createMessageChannel(worker);
The Worker.current call refers to the current worker (the primordial) worker, communicating with the background worker, passed here in parameter of thecreateMessageChannel API.
Now, we have our messaging channel in place, at any time, we can just call send() on the MessageChannel object to pass data to the background worker. But wait, we need a way to retrieve this message channel on the other side, so that we can communicate. For this, you will use the setSharedProperty API, which will put a reference to your message channel so that the child worker can grab the reference and listen to the messages coming in.
So, from the primordial worker you would write:
1.worker.setSharedProperty("mainToBack", mainToBack);
And in your child worker:
1.mainToBack = Worker.current.getSharedProperty("mainToBack");
Note that the String used here should be (to make things clean) something reflect the package of your program, I am using here something obvious to reflect the direction of the communication very clearly. So there we are! To pass data, we can now use our message channel pipeline. Also, remember that the setSharedProperty API can also be used to simply pass values to be used during the initialization of the Worker.
In your application you may want to send data like a String, a Number, an Array or other lightweight types like this, for this you can just use myChannel.send(), the protocol used behind the scenes is AMF3. You can also send custom classes, it will behave as a ByteArray.writeObject/readObject. You would then need to register your class with registerClassAlias. For the ones familiar with Flash Remoting or Flash Media Server, you guys get the idea, your data will be copied and serialized through the rules of AMF3. So no way to pass any DisplayObject between workers for instance, as it is not supported by the AMF3 format. Also, keep in mind, that most data types passed through MessageChannel are serialized (copied) at the exception of a few I will cover later in this article.
So let's say you want to pass an int to a worker, you would write:
On the other side, you would simply write:
1.var value:uint = mainToBack.receive();
You would usually place the receive() call in the Event.CHANNEL_MESSAGE event handler dispatched by the MessageChannel object. Now, the receive() call has two flavors: Synchronous and asynchronous which is actually super useful. In some cases you may want to block and wait until the sending worker has sent the message, that's why there is ablockUntilReceived parameter on the receive() API. By default, it will not block.
You can also queue multiple messages:
1.mainToBack.send(100);
2.mainToBack.send(true);
3.mainToBack.send([10,20]);
On the other side, you can consume them by just checking the messageAvailable property on MessageChannel and consume each of them by keep calling receive().
1.while ( mainToBack.messageAvailable )
2.mainToBack.receive();
So now you may wonder, ok this is really cool but what if I have big amount of data to transfer, like, let's say a BitmapData, or more simply a ByteArray? Well, here comes shared memory to the rescue!
You can find more knowledge on the following link..
http://www.bytearray.org/?p=4423
Thanks,
Bhaskar Pandey