Пакет | flash.system |
Класс | public final class Worker |
Наследование | Worker EventDispatcher Object |
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Объект worker позволяет выполнять код в фоновом режиме параллельно с операциями, выполняющимися в другом объекте worker (включая основной объект worker SWF-файла). В контексте однопоточного выполнения некоторые операции, например обработка большого количества данных в цикле, могут занимать настолько большое время, что основной поток может не справляться с задачей обновления экрана. Это может вызывать дефекты отрисовки и «замораживание» изображения.
Использование объекта worker позволяет выполнять долгосрочные или медленные операции в фоновом режиме. Код каждого объекта worker выполняется в отдельном потоке. Если код одного из объектов worker требует длительного выполнения, это не блокирует выполнение кода других объектов worker. Вместо этого два потока кода выполняются параллельно. Как следствие, объект worker может использоваться для выполнения кода в фоне, позволяя основному потоку приложения обновлять изображение на экране.
Возможность одновременного выполнения различных цепочек кода известна под названием параллелизма.
Примечание. Использование объектов worker для параллельного выполнения поддерживается во Flash Player и в AIR на настольных платформах. Для мобильных платформ параллельное выполнение поддерживается в AIR на платформе Android и iOS. Прежде чем использовать многозадачность, вы можете проверить наличие поддержки многозадачности с помощью статического свойства isSupported.
Экземпляры Worker нельзя создавать напрямую путем вызова конструктора Worker()
. В ситуациях, когда поддерживается использование объектов worker для параллельного выполнения кода, при запуске исполнительной среды автоматически создается объект worker, связанный с основным SWF-файлом. Этот объект называется первоначальным объектом worker.
Каждый дополнительный объект worker создается из отдельного SWF-файла. Чтобы создать новый экземпляр класса Worker, передайте массив ByteArray с байтовым содержимым SWF-файла фонового объекта worker в качестве аргумента метода createWorker()
класса WorkerDomain. Существует три способа получить доступ к байтовому содержимому SWF-файла для этой цели:
-
Использовать метатег [Embed] для внедрения SWF-файла в приложение в виде байтового массива (ByteArray):
// Embed the SWF file [Embed(source="../swfs/BgWorker.swf", mimeType="application/octet-stream")] private static var BgWorker_ByteClass:Class; private function createWorker():void { // create the background worker var workerBytes:ByteArray = new BgWorker_ByteClass(); var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes); // 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(); }
-
Загрузить внешний SWF-файл с помощью загрузчика URLLoader:
// load the SWF file 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); // 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(); }
-
Использовать один SWF-файл и как первоначальный, и как фоновый объект worker:
// 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 if (Worker.current.isPrimordial) { // create a background worker var bgWorker:Worker = WorkerDomain.current.createWorker(swfBytes); // 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(); } else // entry point for the background worker { // set up communication between workers using getSharedProperty() // ... (not shown) // start the background work } }
Объекты worker выполняются изолированно друг от друга и не имеют доступа к памяти, переменным и коду других объектов worker. Тем не менее, существует три механизма для передачи сообщений и данных между экземплярами Worker:
- Общие свойства. Каждый объект worker имеет внутренний набор именованных значений, которые можно считывать и устанавливать из самого этого объекта и из других объектов worker. Для установки значения используется метод
setSharedProperty()
, для чтения — методgetSharedProperty()
. - MessageChannel. Объект MessageChannel предназначен для односторонней отправки сообщений и данных из одного объекта worker в другой. Код в объекте-получателе worker может прослушивать события и получать уведомления о поступлении сообщений. Для создания объекта MessageChannel используйте метод
createMessageChannel()
. - Общий ByteArray: Если свойство
shareable
объекта ByteArray имеет значениеtrue
, для экземпляров этого объекта во всех объектах worker используется одна и та же системная память. Поскольку общая память доступна всем объектам worker одновременно, в программном коде должен быть предусмотрен механизм для предупреждения проблем из-за внезапного изменения данных (такие механизмы приведены в описании свойстваByteArray.shareable
).
Код фонового объекта worker не имеет доступа к некоторым прикладным интерфейсам (API) среды выполнения. В основном сюда относятся прикладные интерфейсы, связанные с пользовательским вводом-выводом и такими элементами операционной системы, как окна или перетаскивание. Как правило, все прикладные интерфейсы (API), которые поддерживаются не во всех контекстах, содержат свойства isSupported
, available
и другие аналогичные свойства, позволяющие перед использованием прикладного интерфейса проверить его доступность в контексте фонового объекта worker.
Примечание. Собственные расширения не поддерживаются для фоновых и вторичных объектов Worker.
Полезный эффект объектов Worker состоит в том, что они снижают вероятность пропуска кадров вследствие блокирования основного потока отрисовки другим кодом. Тем не менее, для объектов Worker требуется дополнительная системная память и ресурсы центрального процессора, что может влиять на итоговую производительность. Поскольку каждый объект Worker использует отдельный экземпляр виртуальной среды исполнения, накладные расходы могут быть велики даже для элементарных объектов worker. При использовании объектов Worker проверяйте работу кода на всех целевых платформах, чтобы убедиться, что нагрузка на систему является приемлемой. Adobe рекомендует не использовать в типовых сценариях более одного или двух фоновых объектов Worker.
Дополнительно
Введение в объекты worker AS3: обработка изображений, автор Шон Блез (Shawn Blais)
Многопоточная физика: использование объектов worker AS3 для физических вычислений, автор Шон Блез (Shawn Blais)
Связанные элементы API
Свойство | Определено | ||
---|---|---|---|
constructor : Object
Ссылка на объект класса или функцию конструктора для данного экземпляра объекта. | Object | ||
current : Worker [статические] [только для чтения]
Предоставляет доступ к объекту worker, содержащему текущий код
| Worker | ||
isPrimordial : Boolean [только для чтения]
Обозначает, является ли данный объект worker первоначальным объектом worker. | Worker | ||
isSupported : Boolean [статические] [только для чтения]
Указывает, поддерживает ли текущий контекст выполнения объекты Worker для организации параллельного выполнения кода. | Worker | ||
state : String [только для чтения]
Текущее состояние объекта worker в пределах его жизненного цикла. | Worker |
Метод | Определено | ||
---|---|---|---|
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void [переопределить]
Регистрирует объект прослушивателя события на объекте EventDispatcher для получения прослушивателем уведомления о событии. | Worker | ||
Создает новый экземпляр MessageChannel для отправки сообщений из объекта worker, для которого производится вызов этого метода, в другой объект worker. | Worker | ||
Посылает событие в поток событий. | EventDispatcher | ||
Извлекает значение, хранящееся в данном объекте worker по строковому ключу. | Worker | ||
Проверяет, имеет ли объект EventDispatcher прослушиватели, зарегистрированные для определенного типа события. | EventDispatcher | ||
Показывает, определено ли заданное свойство для объекта. | Object | ||
Показывает, есть ли экземпляр класса Object в цепи прототипов объекта, заданного в качестве параметра. | Object | ||
Показывает наличие заданного свойства и его перечисляемость. | Object | ||
[переопределить]
Удаляет прослушиватель из объекта EventDispatcher. | Worker | ||
Задает доступность динамического свойства для операций цикла. | Object | ||
Представляет именованное значение, доступное коду, выполняющемуся в SWF объекта worker. | Worker | ||
Запускает выполнение кода объекта worker. | Worker | ||
Останавливает выполнение кода объекта worker. | Worker | ||
Возвращает строковое представление этого объекта, отформатированного в соответствии со стандартами, принятыми для данной локали. | Object | ||
Возвращает строковое представление заданного объекта. | Object | ||
Возвращает элементарное значение заданного объекта. | Object | ||
Проверяет, зарегистрирован ли прослушиватель события для указанного типа события с данным объектом EventDispatcher или любым его предшественником. | EventDispatcher |
Событие | Сводка | Определено | ||
---|---|---|---|---|
[многоадресное событие] Отправляется, когда проигрыватель Flash Player или приложение AIR перемещается в фокус операционной системы и становится активным. | EventDispatcher | |||
[многоадресное событие] Отправляется, когда проигрыватель Flash Player или приложение AIR теряет фокус системы и становится неактивным. | EventDispatcher | |||
Отправляется, когда изменяется значение свойства state объекта worker. | Worker |
current | свойство |
isPrimordial | свойство |
isPrimordial:Boolean
[только для чтения] Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Обозначает, является ли данный объект worker первоначальным объектом worker.
Первоначальный объект worker — это объект worker, в котором выполняется первоначальный SWF-файл. Этот объект worker управляет отрисовкой изображения на экране.
Это свойство может использоваться в приложениях, где первоначальный объект worker и фоновый объект worker представляют собой два экземпляра одного и того же SWF-файла. Альтернативным решением может быть структурирование кода таким образом, чтобы фоновый объект worker использовал код, скомпилированный в отдельный SWF-файл, не совпадающий с первоначальным объектом worker.
Реализация
public function get isPrimordial():Boolean
isSupported | свойство |
isSupported:Boolean
[только для чтения] Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Указывает, поддерживает ли текущий контекст выполнения объекты Worker для организации параллельного выполнения кода.
Если параллельное выполнение доступно, это свойство имеет значение true
.
Реализация
public static function get isSupported():Boolean
state | свойство |
state:String
[только для чтения] Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Текущее состояние объекта worker в пределах его жизненного цикла. Возможные значения этого свойства определены в файле WorkerState.
Реализация
public function get state():String
Связанные элементы API
addEventListener | () | метод |
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Регистрирует объект прослушивателя события на объекте EventDispatcher для получения прослушивателем уведомления о событии. Можно регистрировать прослушиватели событий в любом узле из списка отображения для каждого типа события, фазы и приоритета.
После успешной регистрации прослушивателя событий невозможно изменить его приоритет путем дополнительных вызовов addEventListener()
. Чтобы изменить приоритет прослушивателя, необходимо сначала вызвать метод removeListener()
. Затем можно снова зарегистрировать прослушиватель с новым приоритетом.
Следует учесть, что после регистрации прослушивателя последующие вызовы метода addEventListener()
с другим значением свойства type
или useCapture
приводят к регистрации другого прослушивателя. Например, прослушиватель, изначально зарегистрированный со значением useCapture
, равным true
, прослушивает только во время фазы захвата. Если вызвать метод addEventListener()
еще раз с тем же объектом прослушивателя, но со свойством useCapture
в значении false
, то будет два прослушивателя: один — прослушивающий в фазе захвата, а другой — в целевой фазе и фазе восходящей цепочки.
Невозможно зарегистрировать прослушиватель события только для целевой фазы или для фазы восходящей цепочки. Эти фазы соединены при регистрации, поскольку восходящая цепочка применяется только к предшественникам целевого узла.
Если прослушиватель событий больше не нужен, его можно удалить, вызвав метод removeEventListener()
, иначе могут возникнуть проблемы с памятью. Прослушиватели событий не удаляются из памяти автоматически, так как сборщик мусора не удаляет прослушиватель, пока существует объект, отправляющий соответствующее событие (если параметру useWeakReference
не задано значение true
).
Копирование экземпляра EventDispatcher не приводит к копированию прослушивателей событий, присоединенных к нему. (Если для вновь создаваемого узла требуется прослушиватель событий, его необходимо присоединить после создания узла.) При этом при перемещении экземпляра EventDispatcher присоединенные к нему прослушиватели событий перемещаются вместе с ним.
Если прослушиватель регистрируется для узла в тот момент, когда на нем обрабатывается событие, то в текущей фазе он не запускается, однако может запуститься в следующей фазе потока события, например в фазе восходящей цепочки.
Прослушиватель событий, удаленный из узла во время обработки события на этом узле, будет запускаться текущими операциями. После удаления прослушиватель событий больше не вызывается (если не будет снова зарегистрирован для дальнейшей обработки).
Параметры
type:String — Тип события.
| |
listener:Function — Функция прослушивателя, обрабатывающая событие. Эта функция должна принимать объект Event в качестве единственного параметра и не должна что-либо возвращать , как показано в примере:
function(evt:Event):void Эта функция может иметь любое имя. | |
useCapture:Boolean (default = false ) —
Определяет, работает ли прослушиватель в фазе захвата или в целевой фазе и в фазе восходящей цепочки. Если значение useCapture равно true , прослушиватель обрабатывает событие только во время фазы захвата, но не во время целевой фазы или фазы восходящей цепочки. Если значение useCapture равно false , то прослушиватель обрабатывает событие только в целевой фазе или фазе восходящей цепочки. Чтобы прослушивать событие во всех трех фазах, необходимо вызвать addEventListener() дважды: один раз с useCapture в значении true , а другой — с useCapture в значении false .
| |
priority:int (default = 0 ) — Уровень приоритета прослушивателя событий. Приоритет определяется 32-разрядным целым числом со знаком. Чем больше число, тем выше приоритет. Все прослушиватели событий с приоритетом n обрабатываются перед прослушивателями с приоритетом n-1. Прослушиватели с одинаковым приоритетом обрабатываются в порядке их добавления. Значение приоритета по умолчанию равно 0.
| |
useWeakReference:Boolean (default = false ) — Определяет, является ли ссылка на прослушиватель «сильной» или «слабой». «Сильная» ссылка (по умолчанию) предотвращает удаление прослушивателя сборщиком мусора. «Слабая» ссылка позволяет удалить прослушиватель. Функции элементов уровня класса не подлежат удалению в качестве мусора, вследствие чего можно установить |
createMessageChannel | () | метод |
public function createMessageChannel(receiver:Worker):MessageChannel
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Создает новый экземпляр MessageChannel для отправки сообщений из объекта worker, для которого производится вызов этого метода, в другой объект worker. Код объекта worker, создающий объект MessageChannel, может использовать последний для односторонней отправки сообщений в объект Worker, переданный в аргументе receiver
.
Несмотря на то, что экземпляр MessageChannel может использоваться для отправки сообщений и данных из одного экземпляра Worker в другой, необходимо передать дочернему объекту Worker в виде общего свойства по меньшей мере один экземпляр MessageChannel с помощью метода setSharedProperty()
вызывающего объекта worker.
outgoingChannel = Worker.current.createMessageChannel(bgWorker); incomingChannel = bgWorker.createMessageChannel(Worker.current); bgWorker.setSharedProperty("incoming", outgoingChannel); bgWorker.setSharedProperty("outgoing", incomingChannel); // listen for messages from the receiving MessageChannel // This event is triggered when the background sends a message to this worker incomingChannel.addEventListener(Event.CHANNEL_MESSAGE, incomingMessageHandler);
Параметры
receiver:Worker — Объект worker, который будет получать сообщения, передаваемые через созданный канал сообщений
|
MessageChannel — Объект MessageChannel создается данной операцией
|
getSharedProperty | () | метод |
public function getSharedProperty(key:String):*
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Извлекает значение, хранящееся в данном объекте worker по строковому ключу.
Код дочернего объекта worker может использовать данный метод для извлечения значения уже в конструкторе главного класса SWF-файла данного объекта.
Параметры
key:String — Имя общего свойства, к которому производится доступ
|
* — Значение общего свойства, соответствующее указанному ключу или null , если ключу не сопоставлено никакого значения
|
removeEventListener | () | метод |
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Удаляет прослушиватель из объекта EventDispatcher. При отсутствии прослушивателя, зарегистрированного с объектом EventDispatcher, вызов этого метода не оказывает эффекта.
Параметры
type:String — Тип события.
| |
listener:Function — Удаляемый объект прослушивателя.
| |
useCapture:Boolean (default = false ) —
Указывает, был ли прослушиватель зарегистрирован для фазы захвата или целевой фазы и фазы восходящей цепочки. Если прослушиватель зарегистрирован и для фазы захвата, и для фаз цели и восходящей цепочки, метод removeEventListener() необходимо вызвать дважды: один раз с useCapture() в значении true , а другой раз с useCapture() в значении false .
|
setSharedProperty | () | метод |
public function setSharedProperty(key:String, value:*):void
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Представляет именованное значение, доступное коду, выполняющемуся в SWF объекта worker.
Данный метод можно вызывать перед вызовом метода start()
объекта worker. В этом случае общее свойство доступно коду SWF объекта worker в момент создания в конструкторе.
В параметре value
можно передать практически любой объект. За исключением случаев, описанных ниже, объект в параметре value
не передается по ссылке. Любые изменения объекта, производимые в одном объекте worker после вызова метода setSharedProperty()
не передаются в другой объект worker. Объект копируется путем сериализации в формате AMF3 и последующей десериализации в новый объект в объекте-получателе worker. По этой причине любой объект, не сериализуемый в формате AMF3, в том числе отображаемые объекты, не может передаваться в параметре value
. Для корректной пересылки пользовательского класса его определение должно быть зарегистрировано с помощью функции flash.net.registerClassAlias()
или метаданных [RemoteClass]
. В любом из указанных методов должен использоваться один и тот же псевдоним для обоих версий класса в каждом из объектов worker.
Существует пять типов объектов, которые не копируются между объектами worker, а используются ими совместно:
- Worker
- MessageChannel
- общий ByteArray (объект ByteArray, у которого свойство
shareable
имеет значениеtrue
- объект Mutex
- объект Condition
При передаче экземпляров этих объектов в параметре value
, каждый объект worker получает ссылку на один и тот же исходный объект. Изменения, производимые над экземпляром объекта, моментально становятся доступны в других объектах worker. Кроме того, при многократной отправке с помощью метода setSharedProperty()
одного и того же объекта, принадлежащего одному из этих типов, исполнительная среда не создает новые копии этого объекта в объекте-получателе worker. Вместо этого повторно используется одна и та же ссылка, что снижает расход системной памяти.
Вызов этого метода со значением параметра null
или undefined
для аргумента value
сбрасывает любое ранее установленное значение для указанного значения key
. Сброс значения таким способом удаляет ссылку на это значение, позволяя сборщику мусора утилизировать память.
В качестве аргумента key можно указывать любое значение типа String. Эти общие свойства могут использоваться в любом коде, имеющем доступ к объекту worker. Чтобы избежать нежелательного перезаписывания существующего значения, используйте префиксы, суффиксы или другие приемы, позволяющие сделать имена ключей уникальными.
Параметры
key:String — Имя, под которым производится доступ к общему свойству.
| |
value:* — Значение общего свойства.
|
Связанные элементы API
start | () | метод |
public function start():void
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Запускает выполнение кода объекта worker. Исполнительная среда создает поток worker и вызывает конструктор главного класса SWF объекта worker.
Эта операция является асинхронной. По завершении запуска объекта worker его свойство state
меняет значение на WorkerState.RUNNING
и генерируется событие workerState
.
terminate | () | метод |
public function terminate():Boolean
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Останавливает выполнение кода объекта worker. Вызов этого метода прерывает любой текущий сценарий ActionScript в SWF объекта worker.
ВозвращаетBoolean — true , если выполнение кода объекта worker было прервано, либо false , если объект worker не запускался
|
workerState | Событие |
flash.events.Event
свойство Event.type =
flash.events.Event.WORKER_STATE
Язык версии: | ActionScript 3.0 |
Версии среды выполнения: | Flash Player 11.4, AIR 3.4 |
Отправляется, когда изменяется значение свойства state
объекта worker.
Event.WORKER_STATE
определяет значение свойства type
объекта события workerState
.
Это событие имеет следующие свойства:
Свойство | Значение |
---|---|
bubbles | false |
cancelable | false ; поведение по умолчанию, подлежащее отмене, не определено. |
currentTarget | Объект, активно обрабатывающий объект Event с помощью прослушивателя событий. |
target | Объект, отправивший это событие. |
Пример состоит из трех классов ActionScript: WorkerExample представляет собой главный класс и определяет родительский объект worker. BackgroundWorker — это класс, который выполняет фоновую работу. Этот класс компилируется как основной класс SWF-файла фонового объекта worker. CountResult — это пользовательский класс, используемый для передачи данных между двумя объектами worker. Это позволяет передать данные одним пакетом вместо одиночных значений.
В данном примере фоновый объект worker выполняет циклический счет до значения, заданного родительским объектом worker. По мере решения этой задачи фоновый объект worker отправляет сообщения о ходе выполнения в родительский объект worker. Наконец, по завершении счета фоновый объект worker уведомляет родительский объект worker о завершении своей работы и о времени, затраченном на ее выполнение.
Класс WorkerExample — это основной класс SWF-файла. Он является главным классом первоначального объекта worker. В методе initialize()
создается фоновый объект worker, для чего используется байтовое содержимое класса BackgroundWorker, встраиваемое с помощью тега [Embed]
.
После создания фонового объекта worker вызовом метода WorkerDomain.createWorker()
настраивается связь между двумя объектами worker. Вначале создается набор объектов MessageChannel. Эти объекты передаются в фоновый объект worker путем вызова его метода setSharedProperty()
. Затем производится подписка на событие workerState
фонового объекта Worker и последний запускается вызовом метода start()
.
По мере решения задачи фоновым объектом worker, этот объект отправляет сообщения о ходе выполнения (и впоследствии — о результате выполнения) в родительский объект worker. Родительский объект worker использует эту информацию для обновления индикатора выполнения и текстовой метки.
package { import com.adobe.example.vo.CountResult; import flash.display.Shape; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.net.registerClassAlias; import flash.system.MessageChannel; import flash.system.Worker; import flash.system.WorkerDomain; import flash.system.WorkerState; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.utils.ByteArray; public class WorkerExample extends Sprite { // ------- Embed the background worker swf as a ByteArray ------- [Embed(source="../workerswfs/BackgroundWorker.swf", mimeType="application/octet-stream")] private static var BackgroundWorker_ByteClass:Class; public static function get BackgroundWorker():ByteArray { return new BackgroundWorker_ByteClass(); } private var bgWorker:Worker; private var bgWorkerCommandChannel:MessageChannel; private var progressChannel:MessageChannel; private var resultChannel:MessageChannel; public function WorkerExample() { initialize(); } private function initialize():void { // create the user interface setupStage(); createStatusText(); createProgressBar(); // Register the alias so we can pass CountResult objects between workers registerClassAlias("com.adobe.test.vo.CountResult", CountResult); // Create the background worker bgWorker = WorkerDomain.current.createWorker(BackgroundWorker); // Set up the MessageChannels for communication between workers bgWorkerCommandChannel = Worker.current.createMessageChannel(bgWorker); bgWorker.setSharedProperty("incomingCommandChannel", bgWorkerCommandChannel); progressChannel = bgWorker.createMessageChannel(Worker.current); progressChannel.addEventListener(Event.CHANNEL_MESSAGE, handleProgressMessage) bgWorker.setSharedProperty("progressChannel", progressChannel); resultChannel = bgWorker.createMessageChannel(Worker.current); resultChannel.addEventListener(Event.CHANNEL_MESSAGE, handleResultMessage); bgWorker.setSharedProperty("resultChannel", resultChannel); // Start the worker bgWorker.addEventListener(Event.WORKER_STATE, handleBGWorkerStateChange); bgWorker.start(); } private function handleBGWorkerStateChange(event:Event):void { if (bgWorker.state == WorkerState.RUNNING) { _statusText.text = "Background worker started"; bgWorkerCommandChannel.send(["startCount", 100000000]); } } private function handleProgressMessage(event:Event):void { var percentComplete:Number = progressChannel.receive(); setPercentComplete(percentComplete); _statusText.text = Math.round(percentComplete).toString() + "% complete"; } private function handleResultMessage(event:Event):void { var result:CountResult = resultChannel.receive() as CountResult; setPercentComplete(100); _statusText.text = "Counted to " + result.countTarget + " in " + (Math.round(result.countDurationSeconds * 10) / 10) + " seconds"; } // ------- Create UI ------- private var _currentPercentComplete:int = 0; private var _needsValidation:Boolean = false; private var _statusText:TextField; private var _progressBarRect:Shape; private var _progressBar:Shape; private function setupStage():void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; stage.stageWidth = 800; stage.stageHeight = 600; stage.color = 0xffffff; } private function createStatusText():void { _statusText = new TextField(); _statusText.width = 400; _statusText.height = 25; _statusText.x = (stage.stageWidth - _statusText.width) / 2; _statusText.y = 150; var statusTextFormat:TextFormat = new TextFormat(); statusTextFormat.color = 0xeeeeee; statusTextFormat.font = "Verdana"; statusTextFormat.align = TextFormatAlign.CENTER; statusTextFormat.size = 16; _statusText.defaultTextFormat = statusTextFormat; _statusText.wordWrap = false; _statusText.opaqueBackground = 0x999999; _statusText.selectable = false; _statusText.text = "Initializing..."; addChild(_statusText); } private function createProgressBar():void { _progressBarRect = new Shape(); _progressBarRect.graphics.beginFill(0x000000, 0); _progressBarRect.graphics.lineStyle(2, 0x000000); _progressBarRect.graphics.drawRect(0, 0, 400, 30); _progressBarRect.graphics.endFill(); _progressBarRect.x = (stage.stageWidth - _progressBarRect.width) / 2; _progressBarRect.y = 100; addChild(_progressBarRect); _progressBar = new Shape(); _progressBar.graphics.beginFill(0x0000ee); _progressBar.graphics.drawRect(0, 0, 391, 21); _progressBar.x = _progressBarRect.x + 4; _progressBar.y = _progressBarRect.y + 4; addChild(_progressBar); _progressBar.scaleX = 0; } private function setPercentComplete(percentComplete:int):void { if (_currentPercentComplete == percentComplete) return; _currentPercentComplete = percentComplete; invalidateValue(); } private function invalidateValue():void { if (_needsValidation) return; _needsValidation = true; addEventListener(Event.EXIT_FRAME, validate); } private function validate(event:Event):void { removeEventListener(Event.EXIT_FRAME, validate); _needsValidation = false; _redrawProgressBar(); } private function _redrawProgressBar():void { _progressBar.scaleX = _currentPercentComplete / 100; } } }
В методе initialize()
происходит прием объектов MessageChannel, переданных родительским объектом worker. Эти объекты используются для связи между двумя объектами worker.
Родительский объект worker вызывает метод send()
канала сообщений commandChannel
для отправки сообщения. В фоновом объекте worker исполнительная среда распределяет событие channelMessage
посредством вызова метода handleCommandMessage()
.
Фактическая полезная работа выполняется фоновым объектом worker в методе count()
. По мере выполнения подсчета фоновый объект worker отправляет в родительский объект worker сообщения о ходе выполнения с помощью метода send()
объекта progressChannel
типа MessageChannel. По завершении счета вызывается метод send()
объекта resultChannel
типа MessageChannel.
package com.adobe.example.workers { import com.adobe.example.vo.CountResult; import flash.display.Sprite; import flash.events.Event; import flash.net.registerClassAlias; import flash.system.MessageChannel; import flash.system.Worker; import flash.utils.getTimer; public class BackgroundWorker extends Sprite { private var commandChannel:MessageChannel; private var progressChannel:MessageChannel; private var resultChannel:MessageChannel; public function BackgroundWorker() { initialize(); } private function initialize():void { registerClassAlias("com.adobe.test.vo.CountResult", CountResult); // Get the MessageChannel objects to use for communicating between workers // This one is for receiving messages from the parent worker commandChannel = Worker.current.getSharedProperty("incomingCommandChannel") as MessageChannel; commandChannel.addEventListener(Event.CHANNEL_MESSAGE, handleCommandMessage); // These are for sending messages to the parent worker progressChannel = Worker.current.getSharedProperty("progressChannel") as MessageChannel; resultChannel = Worker.current.getSharedProperty("resultChannel") as MessageChannel; } private function handleCommandMessage(event:Event):void { if (!commandChannel.messageAvailable) return; var message:Array = commandChannel.receive() as Array; if (message != null && message[0] == "startCount") { count(uint(message[1])); } } private function count(targetValue:uint):void { var startTime:int = getTimer(); var onePercent:uint = uint(Math.ceil(targetValue / 100)); var oneHalfPercent:Number = onePercent / 2; var i:uint = 0; while (i < targetValue) { i++; // only send progress messages every one-half-percent milestone // to avoid flooding the message channel if (i % oneHalfPercent == 0) { progressChannel.send(i / onePercent); } } var elapsedTime:int = getTimer() - startTime; var result:CountResult = new CountResult(targetValue, elapsedTime / 1000); resultChannel.send(result); trace("counted to", targetValue.toString(), "in", elapsedTime, "milliseconds"); } } }
registerClassAlias()
, передав ему один и тот же псевдоним в качестве параметра.
package com.adobe.example.vo { public class CountResult { public function CountResult(countTarget:uint=0, countTime:Number=0) { this.countTarget = countTarget; this.countDurationSeconds = countTime; } public var countTarget:uint; public var countDurationSeconds:Number; } }
1. Так как динамическая загрузка удаленного SWF-файла, содержащего код ActionScript, не поддерживается, удаленный SWF-файл необходимо передавать потоку worker в качестве очищенного SWF-файла. 2. Встраивание SWF-файлов (которые содержат код ABC) с помощью тега [Embed] не поддерживается в ОС iOS. Каждый дополнительный поток worker создается из отдельного SWF-файла. Чтобы создать новый экземпляр класса Worker, передайте массив ByteArray с байтовым содержимым SWF-файла фонового объекта worker в качестве аргумента метода createWorker()
класса WorkerDomain.
Существует два способа получить доступ к байтовому содержимому SWF-файла для этой цели: использовать Loader
для загрузки внешнего SWF-файла или использовать URLLoader
.
В следующем примере API-интерфейс Loader
загружает SWF-файл.
package { import flash.display.Loader; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.IOErrorEvent; import flash.net.URLRequest; import flash.system.ApplicationDomain; import flash.system.LoaderContext; import flash.system.MessageChannel; import flash.system.Worker; import flash.system.WorkerDomain; import flash.text.TextField; import flash.text.TextFormat; public class IOSWorkerExample extends Sprite { public var worker:Worker; public var bm:MessageChannel; public var mb:MessageChannel; public var tf:TextField; public var tfrmt:TextFormat; public function IOSWorkerExample() { super(); stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; tf=new TextField(); tfrmt= new TextFormat() tfrmt.size=80; tf.textColor = 0xFFFFF; tf.defaultTextFormat=tfrmt; addChild(tf); //creating the urlRequest object that references the background worker. var _urlRequest:URLRequest = new URLRequest("IOSBackWorker.swf"); var _loader:Loader = new Loader(); var _lc:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler); _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); _loader.load(_urlRequest, _lc); } // This function is called once the swf loading is completed public function completeHandler(e:Event):void { worker = WorkerDomain.current.createWorker(e.target.bytes); bm = worker.createMessageChannel(Worker.current); mb = Worker.current.createMessageChannel(worker); worker.setSharedProperty("btm", bm); worker.setSharedProperty("mtb", mb); //adding event handler on message receive from background bm.addEventListener(Event.CHANNEL_MESSAGE, onBackToMain); worker.start(); bm.receive(true); } public function errorHandler(e:IOErrorEvent):void { trace("In IO ErrorEvent Handler "+e.text); } //This function is called when the main thread receives the message from the background worker. public function onBackToMain(event:Event):void { if(bm.messageAvailable) { // displaying the percentages based on the message received from the background. var progress:Number = bm.receive(); trace("progress "+progress); tf.text= progress.toString(); } } } }
Loader
, в фоновый процесс worker необходимо добавить проверку свойства isPrimordial
, как показано в этом примере:
package { import flash.display.Sprite; import flash.system.MessageChannel; import flash.system.Worker; import flash.utils.ByteArray; import flash.utils.getTimer; public class IOSBackWorker extends Sprite { private var memory:ByteArray = new ByteArray(); private var bm:MessageChannel; private var mb:MessageChannel; public function IOSBackWorker() { if(!Worker.current.isPrimordial) { memory.shareable = true; // creating objects of message channels bm = Worker.current.getSharedProperty("btm"); mb = Worker.current.getSharedProperty("mtb"); // calculating the percentage trace("message came"); var j:Number =1; while (j<1000) { for(var i=0;i<100;i++){} var startTime=getTimer(); // adding delay while (getTimer()-startTime <100); trace(j, (100*j)/1000); var progress:Number=(100*j)/1000; // sending the percentage to the main thread bm.send(progress); j++; } } } } }
Tue Jun 12 2018, 11:34 AM Z