Pacote | flash.system |
Classe | public final class Worker |
Herança | Worker EventDispatcher Object |
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Um worker permite que você execute o código "em fundo" ao mesmo tempo em que outras operações estão em execução em outro worker (incluindo o worker swf principal). Em um contexto que não seja worker, algumas operações, por exemplo o processamento de um grande conjunto de dados em sequência, levam muito tempo para executar e impedem que o thread principal do aplicativo atualize a tela rápido o suficiente. Isso pode causar o congelamento ou travamento da tela.
O uso de um worker permite que você execute uma execução em longo tempo ou operação lenta em plano de fundo. Cada worker executa seu código em um thread separado de execução a partir de outro worker. O código de execução em longo tempo em um worker não bloqueia a execução do código em outro worker. Em vez disso, os dois conjuntos de código são executados em paralelo. Como consequência, um worker pode ser usado para executar o código em plano de fundo enquanto o thread do aplicativo principal fica livre para continuar a atualização da tela.
Este recurso de execução simultânea de múltiplos conjuntos de instrução de códigos é conhecido como concorrência.
Observação: o uso de workers para simultaneidade é suportado no Flash Player e no AIR em plataformas de desktop. Em plataformas móveis, o AIR oferece suporte para simultaneidade no Android e no iOS. Você pode usar a propriedade estática isSupported para verificar se a concorrência é suportada antes de tentar usá-la.
Não é possível criar instâncias Worker fazendo uma chamada para o construtor Worker()
. Em contextos em que o uso dos workers para concorrência é suportado, na inicialização, o runtime cria automaticamente o Worker associado com o SWF principal, conhecido como worker primordial.
Todos os workers adicionais são criados a partir de um SWF diferente. Para criar uma nova instância da classe Worker, transmita um ByteArray com os bytes de um swf do worker em plano de fundo como um argumento à classe do método WorkerDomain createWorker()
. Há três formas comuns para acessar os bytes de um swf para esta finalidade:
-
Utilize a metatag [Embed] para integrar o arquivo .swf ao aplicativo como um 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(); }
-
Carregue um arquivo SWF externo usando o 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(); }
-
Utilize um único swf como o worker primário e de fundo:
// 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 } }
Workers são executados isoladamente de todos os outros e não têm acesso à mesma memória, variáveis e código. Entretanto, há três mecanismos disponíveis para transmitir mensagens e dados entre as instâncias Worker:
- Propriedades compartilhadas: Cada worker possui um conjunto interno de valores nomeados que podem ser definidos e lidos a partir de dentro do próprio worker ou de outros workers. Você pode definir um valor usando o método
setSharedProperty()
e ler um valor usando o métodogetSharedProperty()
. - MessageChannel: Um objeto MessageChannel permite que você envie mensagens e dados unidirecionais a partir de um worker ao outro. Código no worker de destino pode ouvir ou evento para ser notificado quando a mensagem é recebida. Para criar um objeto MessageChannel, use o método
createMessageChannel()
. - ByteArray compartilhável: se propriedade
shareable
de um objeto ByteArray fortrue
, a mesma memória subjacente é usada para instâncias desse ByteArray em todos os workers. Como o código em vários workers pode acessar a memória compartilhada ao mesmo tempo, seu código deve usar os mecanismos descritos na propriedadeByteArray.shareable
para evitar problemas relacionados a trocas de dados inesperadas.
Diversas APIs de runtime relacionado aos mecanismos de entrada e saída do usuário em um worker de plano de fundo. Elas primariamente consistem em APIs relacionadas a entradas do usuário e mecanismos de saída ou elementos do sistema operacional como janelas e arrastar. Como regra, para qualquer API que não seja suportado em todos os contextos, use as propriedades isSupported
, available
e similares para verificar se o API está disponível no contexto do worker de plano de fundo antes de tentar utilizar o API.
Observação: as extensões nativas não são suportados no plano de fundo e trabalhos secundários.
Workers são úteis pois diminuem as chances de diminuição da taxa de quadros devido ao fato de o thread de aplicação de acabamento ser bloqueado por outro código. Entretanto, workers requerem memória do sistema e uso do CPU adicionais, o que pode ser mais custoso ao desempenho geral do aplicativo. Como cada worker utiliza suas próprias instâncias da máquina virtual do runtime, até mesmo o overhead de um worker comum pode ser grande. Ao utilizar workers, teste seu código em todas as plataformas de destino para garantir que as demandas sobre o sistema não sejam tão grandes. A Adobe não recomenda a utilização de mais de um ou dois workers de fundo em um cenário típico.
Saiba mais
Introdução aos Workers do AS3: Processamento de Imagens por Shawn Blais
Física multithread: Como utilizar os Workers do AS3 para mecanismos físicos por Shawn Blais
Elementos da API relacionados
Propriedade | Definido por | ||
---|---|---|---|
constructor : Object
Uma referência ao objeto de classe ou à função de construtor de uma determinada ocorrência de objeto. | Object | ||
current : Worker [estático] [somente leitura]
Fornece acesso ao worker que contém o código atual
| Worker | ||
isPrimordial : Boolean [somente leitura]
Indica se o worker é o worker principal. | Worker | ||
isSupported : Boolean [estático] [somente leitura]
Indica se o contexto do runtime atual suporta o objeto Worker para execuções de código concorrentes. | Worker | ||
state : String [somente leitura]
O estado atual do worker em seu ciclo de vida. | Worker |
Método | Definido por | ||
---|---|---|---|
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void [substituir]
Registra um objeto de ouvinte de evento em um objeto EventDispatcher, de forma que o ouvinte receba a notificação de um evento. | Worker | ||
Cria uma nova instância do MessageChannel pra enviar mensagens a partir do worker no qual o método é chamado a outro worker de destino. | Worker | ||
Envia um evento para o fluxo de eventos. | EventDispatcher | ||
Recupera um valor armazenado neste worker com uma chave nomeada. | Worker | ||
Verifica se o objeto EventDispatcher tem ouvintes registrados para um tipo específico de evento. | EventDispatcher | ||
Indica se um objeto tem uma propriedade especificada definida. | Object | ||
Indica se uma ocorrência da classe Object está na cadeia de protótipos do objeto especificado como o parâmetro. | Object | ||
Indica se a propriedade especificada existe e é enumerável. | Object | ||
[substituir]
Remove um ouvinte do objeto EventDispatcher. | Worker | ||
Define a disponibilidade de uma propriedade dinâmica para operações de repetição. | Object | ||
Fornece um valor nomeado disponível ao código em execução no swf do worker. | Worker | ||
Inicia a execução do worker. | Worker | ||
Interrompe a execução do código deste worker. | Worker | ||
Retorna a representação da string deste objeto, formatado segundo as convenções específicas para a localidade. | Object | ||
Retorna a representação de string do objeto especificado. | Object | ||
Retorna o valor primitivo do objeto especificado. | Object | ||
Verifica se um ouvinte de evento está registrado nesse objeto EventDispatcher ou em qualquer um de seus ancestrais para o tipo de evento especificado. | EventDispatcher |
Evento | Resumo | Definido por | ||
---|---|---|---|---|
[transmissão de evento] Despachado quando o Flash Player ou o aplicativo do AIR ganha o foco do sistema operacional e está se tornando inativo. | EventDispatcher | |||
[transmissão de evento] Despachado quando o Flash Player ou o aplicativo do AIR perde o foco do sistema operacional e está se tornando inativo. | EventDispatcher | |||
Enviado quando o valor da propriedade do estado do worker é alterado. | Worker |
current | propriedade |
isPrimordial | propriedade |
isPrimordial:Boolean
[somente leitura] Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Indica se o worker é o worker principal.
O worker principal é o worker no qual o swf inicial está em execução. Este worker controla o acabamento da tela.
Esta propriedade pode ser utilizada para criar a arquitetura de um aplicativo em que o worker primário e o worker de plano de fundo representam duas instâncias do mesmo arquivo swf. A alternativa é estruturar seu código de modo que o worker de plano de fundo utilize diferentes códigos compilados em um swf diferente a partir do worker primário.
Implementação
public function get isPrimordial():Boolean
isSupported | propriedade |
isSupported:Boolean
[somente leitura] Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Indica se o contexto do runtime atual suporta o objeto Worker para execuções de código concorrentes.
Se a concorrência estiver disponível, o valor desta propriedade será true
.
Implementação
public static function get isSupported():Boolean
state | propriedade |
state:String
[somente leitura] Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
O estado atual do worker em seu ciclo de vida. Os valores possíveis desta propriedade são definidos na classe WorkerState.
Implementação
public function get state():String
Elementos da API relacionados
addEventListener | () | método |
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Registra um objeto de ouvinte de evento em um objeto EventDispatcher, de forma que o ouvinte receba a notificação de um evento. Você pode registrar ouvintes de eventos em todos os nós da lista de exibição de um tipo específico de evento, fase e prioridade.
Depois de registrar um ouvinte de evento com êxito, não será possível alterar a respectiva prioridade por meio de chamadas adicionais para o addEventListener()
. Para alterar a prioridade de um ouvinte, chame primeiramente o removeListener()
. Em seguida, você poderá registrar o ouvinte novamente com o novo nível de prioridade.
Tenha em mente que, após o ouvinte ser registrado, chamadas subsequentes para o addEventListener()
com um valor type
ou useCapture
diferente resultarão na criação de um registro de ouvinte separado. Por exemplo, se você primeiro registrar um ouvinte com o useCapture
definido como true
, ele escutará apenas durante a fase de captura. Se você chamar o addEventListener()
novamente, usando o mesmo objeto de ouvinte, mas com o useCapture
definido como false
, você terá dois ouvintes distintos: um que escuta durante a fase de captura e outro que escuta durante as fases de destino e de bubbling.
Você não pode registrar um ouvinte de evento apenas para a fase de destino ou a fase de bubbling. Essas fases são emparelhadas durante o registro porque o bubbling se aplica apenas aos ancestral do nó-alvo.
Se você não precisar mais de um ouvinte de evento, remova-o, chamando o removeEventListener()
; do contrário, poderão ocorrer problemas de memória. Os ouvintes de evento não são retirados automaticamente da memória porque o coletor de lixo não remove o ouvinte enquanto o objeto de despacho existe (a menos que o parâmetro useWeakReference
seja definido para true
).
Copiar uma ocorrência do EventDispatcher não copia os ouvintes de eventos a ele anexados. (Se o seu recém-criado nó precisar de um ouvinte de evento, anexe o ouvinte após criar o nó). Entretanto, se você mover uma ocorrência do EventDispatcher, os ouvintes de evento anexados se movimentarão com ele.
Se o ouvinte de evento estiver sendo registrado em um nó enquanto um evento estiver sendo processado nesse nó, o ouvinte de evento não será disparado durante a fase atual, mas poderá ser disparado durante uma fase posterior no fluxo de eventos, como a fase de bubbling.
Se um ouvinte de evento for removido de um nó enquanto um evento estiver sendo processado no nó, ele ainda será disparado pelas ações atuais. Depois de removido, o ouvinte de evento nunca mais é chamado novamente (a menos que registrado mais uma vez para processamento futuro).
Parâmetros
type:String — O tipo de evento.
| |
listener:Function — A função de ouvinte que processa o evento. Esta função deve aceitar um objeto Event como seu único parâmetro e não deve retornar nada, como mostra este exemplo:
function(evt:Event):void A função pode ter qualquer nome. | |
useCapture:Boolean (default = false ) —
Determina se o ouvinte trabalha na fase de captura ou nas fases de destino e bubbling. Se useCapture for definido como true , o ouvinte processará o evento apenas durante a fase de captura e não na fase de destino nem de bubbling. Se useCapture for false , o ouvinte processará o evento apenas durante a fase de destino ou de bubbling. Para ouvir o evento em todas as três fases, chame o addEventListener duas vezes, uma vez com o useCapture definido como true , e novamente, com o useCapture definido como false .
| |
priority:int (default = 0 ) — O nível de prioridade do ouvinte de evento. A prioridade é designada por um número inteiro de 32 bits sem sinal. Quanto mais alto o número, maior a prioridade. Todos os ouvintes com prioridade n são processados antes dos ouvintes com prioridade n-1. Se dois ou mais ouvintes compartilham a mesma prioridade, eles são processados pela ordem segundo a qual foram adicionados. A prioridade padrão é 0.
| |
useWeakReference:Boolean (default = false ) — Determina se a referência ao ouvinte é forte ou fraca. Uma referência forte (a padrão) impede que o ouvinte seja coletado como lixo. Uma referência fraca não impede. Funções de membro de nível de classe não estão sujeitas à coleta de lixo, portanto, você pode definir |
createMessageChannel | () | método |
public function createMessageChannel(receiver:Worker):MessageChannel
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Cria uma nova instância do MessageChannel pra enviar mensagens a partir do worker no qual o método é chamado a outro worker de destino. Código no worker que cria o objeto MessageChannel pode usá-lo para enviar mensagens unidirecionais ao objeto Worker especificado como argumento receiver
.
Embora a instância do MessageChannel possa ser utilizada para enviar mensagens e dados de uma instância Worker a outra, ao menos uma instância MessageChannel precisa ser transmitida a um worker filho como uma propriedade compartilhada através de uma chamada ao método setSharedProperty()
do objeto 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);
Parâmetros
receiver:Worker — O worker que receberá mensagens transmitidas através do canal de mensagens criado.
|
MessageChannel — O objeto MessageChannel criado pela operação
|
getSharedProperty | () | método |
public function getSharedProperty(key:String):*
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Recupera um valor armazenado neste worker com uma chave nomeada.
Código em um worker filho pode efetuar uma chamada a esse método para recuperar um valor já no construtor da classe principal do swf worker.
Parâmetros
key:String — Nome da propriedade compartilhada a ser recuperada
|
* — O valor da propriedade compartilhada armazenada com uma chave específica, ou null se nenhum valor for armazenado para a chave especificada.
|
removeEventListener | () | método |
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Remove um ouvinte do objeto EventDispatcher. Se não existir um ouvinte correspondente registrado com o objeto EventDispatcher, uma chamada para esse método não terá efeito.
Parâmetros
type:String — O tipo de evento.
| |
listener:Function — O objeto de ouvinte a remover.
| |
useCapture:Boolean (default = false ) —
Especifica se o ouvinte foi registrado na fase de captura ou nas fases de destino e bubbling. Se o ouvinte foi registrado para as fases de destino e de bubbling, duas chamadas para o removeEventListener() serão necessárias para remover as duas, uma chamada com o useCapture() definido como true e outra chamada com o useCapture() definido como false .
|
setSharedProperty | () | método |
public function setSharedProperty(key:String, value:*):void
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Fornece um valor nomeado disponível ao código em execução no swf do worker.
Você pode efetuar uma chamada a este método antes de efetuar uma chamada ao método start()
do worker. Neste caso, a propriedade compartilhada está disponível para codificar no swf do worker no momento da construção.
O valor passou ao parâmetro value
pode ser qualquer objeto. Diferentemente das exceções descritas abaixo, qualquer objeto transmitido ao parâmetro value
não é transmitido por referência. Qualquer alteração feita no objeto em um worker após a chamada ao setSharedProperty()
não é transportada ao outro worker. O objeto é copiado quando é criado em série ao formato AMF3 e removido da série em um novo objeto, no worker de destino. Por este motivo, qualquer objeto que puder ser criado em série em um formato AMF3, incluindo os objetos em exibição, não podem ser transmitidos ao parâmetro value
. Para transmitir de forma adequada uma classe personalizada, a definição da classe pode ser registrada usando a função flash.net.registerClassAlias()
ou o metadado [RemoteClass]
. Com tais técnicas, o mesmo alias pode ser usado para ambas as versões do worker da classe.
Há cinco tipos de objetos que uma exceção à regra de que os objetos não são compartilhados entre os workers:
- O trabalhador
- MessageChannel
- ByteArray compartilhável (um objeto ByteArray com a propriedade
shareable
definida comotrue
- Mutex
- Condição
Se você transmitir uma instância destes objetos ao parâmetro value
, cada worker terá uma referência ao mesmo objeto adjacente. As alterações feitas a uma instância em um worker são imediatamente disponíveis em outros workers. Além disso, se você transportar a mesma instância desses objetos mais de uma vez usando setSharedProperty()
, o runtime não criará uma nova cópia do objeto no worker de destino. Em vez disso, a mesma referência é reutilizada, reduzindo o uso da memória do sistema.
Efetuar uma chamada a este método com null
ou undefined
para o argumento value
limpa qualquer valor determinado anteriormente para o argumento key
especificado. Limpar um valor desta maneira remove a referência a ele, permitindo que o lixo seja coletado.
Você pode usar qualquer valor String no argumento key. Estas propriedades compartilhadas estão disponíveis para qualquer código que tenha acesso ao worker. Para evitar a sobrescrição não intencional de um valor, considere o uso de um prefixo, sufixo ou mecanismo similar para tentar tonar os nomes principais únicos.
Parâmetros
key:String — O nome sob o qual a propriedade compartilhada é armazenado.
| |
value:* — O valor da propriedade compartilhada.
|
Elementos da API relacionados
start | () | método |
public function start():void
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Inicia a execução do worker. O runtime cria um thread o worker e efetua uma chamada ao construtor da classe principal do swf do worker.
Esta operação é assíncrona. Assim que a inicialização do worker estiver concluída, ele altera sua propriedade state
para WorkerState.RUNNING
e envia um evento workerState
.
terminate | () | método |
public function terminate():Boolean
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Interrompe a execução do código deste worker. Efetuar uma chamada a este método aborta qualquer ActionScript atual no swf do worker.
RetornaBoolean — true se o código no worker estiver em execução e for interrompido, ou false se o worker nunca for inicializado.
|
workerState | Evento |
flash.events.Event
propriedade Event.type =
flash.events.Event.WORKER_STATE
Versão da linguagem: | ActionScript 3.0 |
Versões de runtime: | Flash Player 11.4, AIR 3.4 |
Enviado quando o valor da propriedade state
do worker é alterado.
Event.WORKER_STATE
define o valor do tipo de propriedade type
de um objeto de evento workerState
.
Esse evento tem as seguintes propriedades:
Propriedade | Valor |
---|---|
bubbles | false |
cancelable | false ; não há comportamento padrão a ser cancelado. |
currentTarget | O objeto que está processando ativamente o objeto Event com um ouvinte de evento. |
target | O objeto que despachou este evento. |
Este exemplo é composto por três classes ActionScript: WorkerExample é a classe principal e, também, o worker pai. BackgroundWorker é a classe que executa a tarefa de plano de fundo. É traduzida como a classe principal do swf do worker de plano de fundo. CountResult é uma classe personalizada utilizada para transmitir os dados entre os dois workers como um objeto único, não como valores múltiplos.
Neste exemplo, o worker de plano de fundo conta com uma repetição máxima, com um número especificado pelo worker pai. À medida que progrido em seu trabalho, envia mensagens de progresso o worker pai. Por fim, quando a contagem é finalizada, o worker de plano de fundo envia uma mensagem ao worker pai notificando sobre a conclusão e o tempo gasto na contagem.
A classe WorkerExample é a classe principal do swf, sendo assim é a classe principal do worker principal. No método initialize()
, o código cria o objeto worker de plano de fundo utilizando os bytes da classe BackgroundWorker, que são incorporados usando uma tag [Embed]
.
Após a criação de um worker de plano de fundo através de uma chamada ao WorkerDomain.createWorker()
, o código define a comunicação entre os workers. O primeiro código cria um conjunto de objetos MessageChannel. Ele transporta esses conjuntos ao worker de plano de fundo efetuando uma chamada ao método setSharedProperty()
. Finalmente, faz um registro para o evento workerState
do objeto Worker e inicia o worker efetuando uma chamada ao método start()
.
À medida que o worker de plano de fundo executa sua tarefa, envia mensagens de progresso (e, ao final, o resultado) ao worker pai. O worker pai utiliza estas informações para atualizar a barra de progresso e o indicador de texto.
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; } } }
No método initialize()
, ele recebe os objetos MessageChannel transmitidos pelo worker pai. Eles são utilizados para a comunicação entre os dois workers.
O worker pai efetua uma chamada ao método send()
no canal de mensagem commandChannel
para enviar uma mensagem. Dentro do worker de plano de fundo, o runtime envia o evento channelMessage
efetuando uma chamada ao método handleCommandMessage()
.
A tarefa verdadeira do worker de plano de fundo ocorre no método count()
. À medida que o worker de plano de fundo prossegue com sua contagem, envia mensagens de progresso ao worker pai efetuando uma chamada ao método send()
no objeto MessageChannel progressChannel
. Ao finalizar a contagem, efetua uma chamada ao método send()
no objeto MessageChannel resultChannel
.
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()
usando o nome do mesmo alias.
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. Como não é possível carregar dinamicamente um SWF remoto que contém o código ActionScript, o SWF remoto precisa ser transmitido para o worker como um arquivo SWF sem código. 2. Não é possível incorporar SWFs (que utilizam o código ABC) usando a tag [Embed] no iOS. Todos os workers adicionais são criados a partir de um SWF diferente. Para criar uma nova instância da classe Worker, transfira um ByteArray com os bytes do SWF do worker em segundo plano como um argumento para a classe do método WorkerDomain createWorker()
.
Há duas maneiras comuns de acessar os bytes de um SWF para esta finalidade no iOS: a primeira é usar oLoader
para carregar um arquivo SWF externo, e a segunda é usar o URLLoader
para carregar o arquivo SWF.
O exemplo a seguir usa a API do Loader
para carregar o arquivo 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
é necessário colocar uma verificação de propriedade isPrimordial
no worker em segundo plano, conforme mostra este exemplo.
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++; } } } } }
Wed Jun 13 2018, 11:10 AM Z