Создание потоков worker и управление ими

Flash Player 11.4 и более поздних версий, Adobe AIR 13.4 и более поздних версий для ПК

Первым шагом на пути к использованию потока worker для параллелизма является создание фонового потока worker. Для создания потока worker используются объекты двух типов. Во-первых, это экземпляр Worker, который представляет создаваемый поток. Во-вторых, это объект WorkerDomain, который создает экземпляр Worker и управляет действующими объектами Worker в приложении.

Когда среда выполнения загружается, он автоматически создает объект WorkerDomain. Среда выполнения также автоматически создает поток worker для главного SWF-файла приложения. Первый поток worker называется первичным потоком worker.

Так как для приложения создается только один объект WorkerDomain, доступ к экземпляру WorkerDomain обеспечивается с помощью статического свойства WorkerDomain.current.

В любое время можно получить доступ к текущему экземпляру Worker (то есть к потоку worker, в котором выполняется текущий код), используя статическое свойство Worker.current.

Создание объекта Worker из SWF-файла

Тогда как главный SWF выполняется в первичном потоке worker, фоновый поток worker выполняет код одного SWF-файла. Чтобы использовать фоновый поток worker, необходимо написать и скомпилировать код потока worker в виде SWF-файла. Чтобы создать фоновый поток worker, родительскому потоку worker требуется доступ к байтам этого SWF-файла в виде объекта ByteArray. Этот объект ByteArray передается методу createWorker() объекта WorkerDomain с целью фактического создания потока worker.

Получить SWF фонового потока worker в виде объекта ByteArray можно тремя основными способами.

Внедрение SWF потока worker

Используйте метатег [Embed] для внедрения SWF потока worker в главный SWF-файл в виде объекта ByteArray.

[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 
}

SWF потока worker компилируется в главный SWF как подкласс ByteArray с именем BgWorker_ByteClass. В результате создания экземпляра этого класса мы получаем объект ByteArray, предварительно заполненный байтами SWF-файла потока worker.

Загрузка внешнего SWF-файла потока worker

Используйте объект URLLoader для загрузки внешнего SWF файла. SWF-файл должен находиться в том же домене безопасности, например SWF-файл, загруженный из того же интернет-домена, что и главный SWF-файл, или включенный в пакет приложения AIR.

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 доступны в свойстве data этого объекта URLLoader (event.target.data в нашем примере).

Использование главного SWF в качестве SWF потока worker

Можно использовать один SWF-файл и для главного SWF, и для SWF потока worker. Используйте свойство 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 или в фоновом, проверьте свойство isPrimordial текущего объекта Worker, как показано в примере.

Начало выполнения потока worker

После создания потока worker выполнение его кода запускается посредством вызова метода start() объекта Worker. Операция start() происходит не сразу. Чтобы узнать, когда выполняется поток worker, зарегистрируйте прослушиватель для события workerState объекта Worker. Это событие отправляется, когда объект Worker переходит от одного состояния жизненного цикла к другому, например, когда он начинает выполнение кода. В обработчике событий workerState проверьте, что свойство state объекта Worker имеет значение 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

Можно в любое время получить доступ к набору выполняемых потоков worker в приложении с помощью метода listWorkers() класса WorkerDomain. Этот метод возвращает набор потоков worker, у которых свойство state имеет значение WorkerState.RUNNING, в том числе первичный поток worker. Если поток worker не запущен или его выполнение уже остановлено, он не включается в набор.

Если поток worker больше не нужен, можно вызвать метод terminate() объекта Worker, чтобы завершить работу потока worker и освободить используемую им память и другие системные ресурсы.