Hi there, I encountered a really strange behavior with Flex and already tried StackOverflow and Reddit, but didn't get any reponse, so I'm trying here again:
I have the following scenario: I am using a MessageChannel to communicate with a background worker in a flex application. Since the code is to eventually be transformed into a library, it should also be able to handle malformed input (e.g. sending classes via the channel for which no class alias is registered in the background worker). In this case I want to abort the worker. My code is the following: package{ import flash.display.Sprite; import flash.events.Event; import flash.system.MessageChannel; import flash.system.Worker; public class BW extends Sprite { /** Incoming channel */ private var fromCoordinatorChannel:MessageChannel; /** Outgoing channel */ private var toCoordinatorChannel:MessageChannel; public function BW() { super(); initChannels(); } /** * Get channels from shared property and attach event listener */ private function initChannels():void { // Get channnels from shared property fromCoordinatorChannel = Worker.current.getSharedProperty("toWorkerChannel"); toCoordinatorChannel = Worker.current.getSharedProperty("fromWorkerChannel"); // Attach event listener for incoming messages fromCoordinatorChannel.addEventListener(Event.CHANNEL_MESSAGE, onIncomingMessage); } /** * Event handler for incoming messages on the channel. * @param event Event that came in */ private function onIncomingMessage(event:Event):void { handleIncoming(); } /** * Get oldest message from channel and handle it */ private function handleIncoming():void { if(fromCoordinatorChannel.messageAvailable) { try { var wm:Object = fromCoordinatorChannel.receive(true); } catch(e:Error) { fromCoordinatorChannel.close(); trace("Invalid type of package sent - could not be deserialized."); // Kill myself fromCoordinatorChannel = null; toCoordinatorChannel = null; Worker.current.setSharedProperty("toWorkerChannel", null); Worker.current.setSharedProperty("fromWorkerChannel", null); Worker.current.terminate(); } } } }} And in the primordial worker: <?xml version="1.0" encoding="utf-8"?><s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Script> <![CDATA[ import mx.events.FlexEvent; var worker:Worker; var to:MessageChannel; var from:MessageChannel; var graveyard:Array = new Array(); private function removeWorkerIfFailed():void { if(worker && worker.state == WorkerState.TERMINATED) { from.close(); worker = null; // What the actual f***? If I allow this channel to be garbage collected, it breaks. If I prevent that, it doesn't (o.Ó) graveyard.push(to); to = null; from = null; } } protected function button1_clickHandler(event:MouseEvent):void { registerClassAlias("Example", Example); // Create worker and channels worker = WorkerDomain.current.createWorker(Workers.BW); to = Worker.current.createMessageChannel(worker); from = worker.createMessageChannel(Worker.current); // Attach event listener to status of worker so its reference can be deleted when it fails worker.addEventListener(Event.WORKER_STATE,function(event:Event):void {removeWorkerIfFailed();}); // Set shared properties so worker can access channels worker.setSharedProperty("toWorkerChannel", to); worker.setSharedProperty("fromWorkerChannel", from); // Attach event listener for incoming messages from.addEventListener(Event.CHANNEL_MESSAGE, function(event:Event):void { trace('incoming'); }); // Start the worker worker.start(); var example1:Example = new Example("one"); to.send(example1); } ]]> </fx:Script> <s:Button label="Do it" click="button1_clickHandler(event)"> </s:Button></s:WindowedApplication> Add the Example class package{ import flash.utils.IDataInput; import flash.utils.IDataOutput; import flash.utils.IExternalizable; public class Example implements IExternalizable { public var name:String; public function Example(name:String) { this.name = name; } public function readExternal(input:IDataInput):void { name = input.readUTF(); } public function writeExternal(output:IDataOutput):void { output.writeUTF(name); } }} The problem is the following: If I remove the line in the removeWorkerIfFailed() that pushes a reference to the array (thereby preventing the channel from being garbage collected), the main application freezes. The debugger does not show any active function calls. As long as that line is there, everything works fine. To reiterate: I know that in order to fix it, I need to call the registerClassAlias(...) also in the background worker, but I am trying to handle precisely this case that someone throws something wrong at the background worker. I'm really thankful for any pointers Thanks, Michael