我有以下场景:我使用MessageChannel与Flex应用程序中的后台工作程序进行通信。由于代码最终将被转换为库,因此它还应该能够处理格式错误的输入(例如,通过在后台工作程序中未注册类别名的通道发送类)。在这种情况下,我想中止工人。我的代码如下:
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();
}
}
}
}
}
在原始工人中:
<?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>
添加Example类
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);
}
}
}
问题如下:如果我删除了removeWorkerIfFailed()中推送对数组的引用(从而阻止通道被垃圾回收)的行,则主应用程序会冻结。调试器不显示任何活动的函数调用。只要那条线存在,一切正常。
重申:我知道为了解决这个问题,我需要在后台工作程序中调用registerClassAlias(...),但我正在尝试处理这种情况,即有人抛出错误的地方后台工作者。
谢谢