创建和管理 worker

用于桌面平台的 Flash Player 11.4 和更高版本以及 Adobe AIR 13.4 和更高版本

将 worker 用于并发的第一步是创建后台 worker。您可以使用两种类型的对象来创建 worker。第一种是您所创建的 Worker 实例。另一种是 WorkerDomain 对象,其可创建 Worker 并管理应用程序中的运行 Worker 对象。

当运行时加载时,其将自动创建 WorkerDomain 对象。运行时还可自动为应用程序的主 swf 创建 worker。第一个 worker 称为 原始 worker

因为应用程序只有一个 WorkerDomain 对象,您可以使用静态 WorkerDomain.current 属性访问 WorkerDomain 实例。

您可以使用静态 Worker.current 属性,随时访问当前 Worker 实例(当前代码在其中运行的 worker)。

从 swf 中创建 Worker 对象

正当主 swf 在原始 worker 内运行时,后台 worker 执行单个 swf 文件的代码。要使用后台 worker,您必须将 worker 代码创作和编译为 swf 文件。要创建后台 worker,父 worker 需要作为 ByteArray 对象访问该 swf 文件的字节。将该 ByteArray 传递到 WorkerDomain 对象的 createWorker() 方法,从而实际创建 worker。

有三种主要方法可以作为 ByteArray 对象得到后台 worker swf。

嵌入 worker swf

使用 [Embed] 元标签可以将 worker swf 作为 ByteArray 嵌入主 swf:

[Embed(source="../swfs/BgWorker.swf", mimeType="application/octet-stream")] 
private static var BgWorker_ByteClass:Class; 
private function createWorker():void 
{ 
    var workerBytes:ByteArray = new BgWorker_ByteClass(); 
    var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes); 
     
    // ... set up worker communication and start the worker 
}

worker swf 作为名为 BgWorker_ByteClass 的 ByteArray 子类编译进主 swf。创建该类实例可为您提供预先填充了 worker swf 字节的 ByteArray。

加载外部 worker swf

使用 URLLoader 对象加载外部 swf 文件。swf 文件必须来自相同的安全域,例如与主 swf 加载自同一个 Internet 域的 swf 文件或包含在 AIR 应用程序包中的 swf 文件。

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); 
     
    // ... set up worker communication and start the worker 
}

当 URLLoader 完成加载 swf 文件后,swf 的字节在 URLLoader 对象的 data 属性(在本示例中为 e ent.target.data )中可用。

将主 swf 用作 worker swf

您可以将单个 swf 用作主 swf 和 worker swf。使用主显示类的 loaderInfo.bytes 属性可以访问 swf 的字节。

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

如果使用该技巧,那么使用 if 语句可以在主类的构造函数或其调用的方法中分支 swf 文件代码。要确定代码是在主 worker 中运行还是在后台 worker 中运行,请检查当前 Worker 对象的 isPrimordial 属性,如示例中所示。

开始 worker 执行

在创建了 worker 之后,通过调用 Worker 对象的 start() 方法开始其代码执行。 start() 操作不会立即发生。要了解 worker 何时运行,请为 Worker 对象的 workerState 事件注册一个侦听器。当 Worker 对象在其生存期内切换状态时(例如,当其开始执行代码时),对该事件进行调度。在 workerState 事件处理函数中,请检查 Worker 对象的 state 属性是否为 WorkerState.RUNNING 。在那时,worker 正在运行并且其主类的构造函数已经运行。以下代码列表显示注册 workerState 事件和调用 start() 方法的示例:

// 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(); 
private function workerStateHandler(event:Event):void 
{ 
    if (bgWorker.state == WorkerState.RUNNING) 
    { 
        // The worker is running. 
        // Send it a message or wait for a response. 
    } 
}

管理 worker 执行

使用 WorkerDomain 类的 listWorkers() 方法,您可以随时访问应用程序中运行的一组 worker。该方法返回 state 属性为 WorkerState.RUNNING 的一组 worker,包括原始 worker。如果 worker 尚未开始或已停止执行,则其不包含在内。

如果您不再需要 worker,则可以调用 Worker 对象的 terminate() 方法以关闭 worker 并释放其内存和其他系统资源。