Paquete | flash.system |
Clase | public final class Worker |
Herencia | Worker EventDispatcher Object |
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Un programa de trabajo permite al usuario ejecutar código "en segundo plano" al mismo tiempo que se ejecutan otras operaciones en otro programa de trabajo (incluido el programa de trabajo del swf principal). En un contexto sin programas de trabajo, algunas operaciones (por ejemplo, el procesamiento en bucle de un conjunto grande de datos) tardan tanto en ejecutarse que impiden que el subproceso de la aplicación principal pueda actualizar la pantalla con la velocidad necesaria. Esto provoca el bloqueo o los cortes de visualización de la pantalla.
Si se utiliza un programa de trabajo, es posible realizar una ejecución larga o una operación corta en segundo plano. Cada programa de trabajo ejecuta su código en un subproceso independiente de la ejecución del resto de programas de trabajo. El código de ejecución larga de un programa de trabajo no bloquea la ejecución del código en otro programa de trabajo. Los dos conjuntos de código se ejecutan en paralelo. En consecuencia, un programa de trabajo se puede utilizar para ejecutar código en segundo plano mientras el subproceso de la aplicación principal permanece libre para actualizar la visualización de la pantalla.
Esta capacidad ejecutar varios conjuntos de instrucciones de código al mismo tiempo recibe el nombre de simultaneidad.
Nota: el uso de programas de trabajo para simultaneidad se admite en Flash Player y en plataformas de AIR para escritorio. En las plataformas móviles, la simultaneidad se admite en AIR tanto en Android como en iOS. Se puede utilizar la propiedad estática isSupported para comprobar si se admite la simultaneidad antes de intentar usarla.
No es posible crear instancias de Worker directamente llamando al constructor Worker()
. En contextos en los que se admite el uso de programas de trabajo para simultaneidad, el motor de ejecución crea al inicio automáticamente el programa de trabajo asociado al SWF principal, conocido como programa de trabajo primordial.
Cada programa de trabajo adicional se crea desde un swf independiente. Para crear una nueva instancia de la clase Worker, transfiera un objeto ByteArray con los bytes del swf del programa de trabajo de segundo plano como argumento del método createWorker()
de la clase WorkerDomain. Hay tres formas comunes de acceder a los bytes de un swf para este fin:
-
Utilizar la metaetiqueta [Embed] para incorporar el archivo .swf en la aplicación como un 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(); }
-
Cargar un archivo SWF externo con un 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(); }
-
Utilizar un solo swf como programa de trabajo primordial y de segundo plano:
// 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 } }
Los programas de trabajo se ejecutan aislados entre sí y no tienen acceso a la misma memoria, variables ni código. Sin embargo, existen tres mecanismos disponibles para transferir datos y mensajes entre instancias de programas de trabajo:
- Propiedades compartidas: cada programa de trabajo dispone de un conjunto interno de valores que se pueden definir y leer tanto desde el propio programa de trabajo como desde otros programas de trabajo. Es posible establecer un valor con el método
setSharedProperty()
y leer un valor con el métodogetSharedProperty()
. - MessageChannel: un objeto MessageChannel permite enviar mensajes unidireccionales y datos entre programas de trabajo. El código del programa de trabajo receptor puede detectar la notificación de un evento cuando se recibe un mensaje. Para crear un objeto MessageChannel, utilice el método
createMessageChannel()
. - ByteArray compartible: si la propiedad
shareable
de un objeto ByteArray estrue
, se utilizará la misma memoria subyacente para instancias de dicho ByteArray en todos los programas de trabajo. Dado que el código de varios programas de trabajo puede acceder a la memoria compartida al mismo tiempo, el código debe utilizar los mecanismos descritos en la descripción de la propiedadShareable.byteArray
para evitar problemas debidos a cambios inesperados en los datos.
En el código que se ejecuta en un programa de trabajo en segundo plano, algunas API del motor de ejecución no están disponibles. Básicamente se trata de las API relacionadas con mecanismos de entrada y salida de usuario, o elementos del sistema operativo como las ventanas o las acciones de arrastrar y soltar. Como norma, para cualquier API no admitida en todos los contextos, puede utilizar la propiedad isSupported
, available
(o propiedades similares) para comprobar si la API está disponible en el contexto del programa de trabajo en segundo plano antes de intentar utilizarla.
Nota: las extensiones nativas no son compatibles con programas de trabajo de fondo y secundarios.
Los programas de trabajo son útiles, ya que reducen las posibilidades de pérdidas de velocidad de fotogramas debidas al bloqueo del subproceso principal por parte de otro código. No obstante, los programas de trabajo requieren memoria adicional del sistema y mayor uso de CPU, y esto puede afectar significativamente al rendimiento general de la aplicación. Dado que cada programa de trabajo utiliza su propia instancia de la máquina virtual del motor de ejecución, incluso la sobrecarga de un programa de trabajo trivial puede ser muy grande. Cuando utilice programas de trabajo, pruebe el código en todas las plataformas de destino para garantizar que no exigen demasiados recursos de uso del sistema. Adobe recomienda no utilizar más de uno o dos programas de trabajo en segundo plano en un escenario típico.
Más información
Introducción a programas de trabajo de AS3: Procesamiento de imágenes, por Shawn Blais
Física de subprocesos: Uso de programas de trabajo de AS3 para un motor físico, por Shawn Blais
Elementos de API relacionados
Propiedad | Definido por | ||
---|---|---|---|
constructor : Object
Una referencia a la clase de objeto o función constructora para una instancia de objeto determinada. | Object | ||
current : Worker [estática] [solo lectura]
Proporciona acceso al programa de trabajo que contiene el código actual
| Worker | ||
isPrimordial : Boolean [solo lectura]
Indica si este programa de trabajo es el primordial. | Worker | ||
isSupported : Boolean [estática] [solo lectura]
Indica si el contexto de motor de ejecución actual admite el uso de objetos Worker para ejecución de código simultánea. | Worker | ||
state : String [solo lectura]
El estado actual del programa de trabajo en su ciclo de vida. | Worker |
Método | Definido por | ||
---|---|---|---|
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void [override]
Registra un objeto de detector de eventos con un objeto EventDispatcher, de modo que el detector reciba la notificación de un evento. | Worker | ||
Crea una nueva instancia de MessageChannel para enviar mensajes desde el programa de trabajo en el que se llama al método a otro programa de trabajo receptor. | Worker | ||
Distribuye un evento en el flujo del evento. | EventDispatcher | ||
Recupera un valor almacenado en este programa de trabajo con una clave determinada. | Worker | ||
Comprueba si el objeto EventDispatcher tiene detectores registrados para un tipo concreto de evento. | EventDispatcher | ||
Indica si un objeto tiene definida una propiedad especificada. | Object | ||
Indica si hay una instancia de la clase Object en la cadena de prototipo del objeto especificado como parámetro. | Object | ||
Indica si existe la propiedad especificada y si es enumerable. | Object | ||
[override]
Elimina un detector del objeto EventDispatcher. | Worker | ||
Establece la disponibilidad de una propiedad dinámica para operaciones de bucle. | Object | ||
Proporciona un valor determinado disponible en el código que se ejecuta en el swf del programa de trabajo. | Worker | ||
Inicia la ejecución del programa de trabajo. | Worker | ||
Detiene la ejecución del código de este programa de trabajo. | Worker | ||
Devuelve la representación de cadena de este objeto, con formato según las convenciones específicas de configuración regional. | Object | ||
Devuelve la representación de cadena del objeto especificado. | Object | ||
Devuelve el valor simple del objeto especificado. | Object | ||
Comprueba si hay registrado un detector de eventos con este objeto EventDispatcher o con cualquiera de sus ascendientes para el tipo de evento concreto. | EventDispatcher |
Evento | Resumen | Definido por | ||
---|---|---|---|---|
[evento broadcast] Se distribuye cuando Flash Player o AIR pasan a estar activos. | EventDispatcher | |||
[evento broadcast] Se distribuye cuando Flash Player o de AIR pasan a estar inactivos. | EventDispatcher | |||
Se distribuye cuando cambia el valor de la propiedad state del programa de trabajo. | Worker |
current | propiedad |
isPrimordial | propiedad |
isPrimordial:Boolean
[solo lectura] Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Indica si este programa de trabajo es el primordial.
El programa de trabajo primordial es el programa de trabajo en el que se ejecuta el swf inicial. Este programa de trabajo controla el procesamiento de la pantalla.
Esta propiedad se puede utilizar para construir una aplicación en la que el programa de trabajo primordial y el programa de trabajo en segundo plano sean dos instancias del mismo archivo swf. La alternativa es construir el código de modo que el programa de trabajo en segundo plano utilice un código distinto compilado en otro swf que no sea el del programa de trabajo primordial.
Implementación
public function get isPrimordial():Boolean
isSupported | propiedad |
isSupported:Boolean
[solo lectura] Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Indica si el contexto de motor de ejecución actual admite el uso de objetos Worker para ejecución de código simultánea.
Si la simultaneidad está disponible, el valor de esta propiedad es true
.
Implementación
public static function get isSupported():Boolean
state | propiedad |
state:String
[solo lectura] Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
El estado actual del programa de trabajo en su ciclo de vida. Los valores posibles de esta propiedad se definen en la clase WorkerState.
Implementación
public function get state():String
Elementos de API relacionados
addEventListener | () | método |
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Registra un objeto de detector de eventos con un objeto EventDispatcher, de modo que el detector reciba la notificación de un evento. Puede registrar detectores de eventos en todos los nodos de la lista de visualización para un tipo concreto de evento, fase y prioridad.
Una vez registrado correctamente un detector de eventos, no puede cambiar su prioridad mediante llamadas adicionales a addEventListener()
. Para cambiar la prioridad de un detector, en primer lugar debe llamar a removeListener()
. Seguidamente, puede volver a registrar el nuevo nivel de prioridad.
Recuerde que, una vez registrado el detector, las siguientes llamadas a addEventListener()
con un valor type
o useCapture
distinto tendrán como resultado la creación de un registro independiente del detector. Por ejemplo, si registra primero un detector con useCapture
definido como true
, detectará únicamente durante la fase de captura. Si vuelve a llamar a addEventListener()
con el mismo objeto detector, pero con useCapture
definido como false
, tendrá dos detectores independientes: uno que detecta durante la fase de captura y otro que lo hace durante las fases de destino y de propagación.
No es posible registrar un detector de eventos únicamente para la fase de destino o la fase de propagación. Dichas fases se acoplan durante el registro, ya que la propagación sólo se aplica a los ascendientes del nodo de destino.
Si ya no necesita ningún detector de eventos, elimínelo llamando a removeEventListener()
; de lo contrario, podrían surgir problemas de memoria. Los detectores de eventos no se eliminan automáticamente de la memoria, ya que el recolector de datos innecesarios no elimina el detector siempre que el objeto distribuido exista (a no ser que el parámetro useWeakReference
se establezca en true
).
Al copiar una instancia EventDispatcher no se copian los detectores de eventos asociados. (Si el nodo recién creado necesita un detector de eventos, debe asociarlo después de crear el nodo.) Sin embargo, si mueve una instancia EventDispatcher, los detectores de eventos asociados se moverán también.
Si el detector de eventos se registra en un nodo mientras se procesa un evento en dicho nodo, el detector de eventos no se desencadenará durante la fase actual, aunque sí se desencadenará en una fase posterior del flujo del evento, por ejemplo, en la fase de propagación.
Si un detector de eventos se elimina de un nodo mientras se procesa un evento en dicho nodo, las acciones actual seguirán desencadenándolo. Una vez eliminado, el detector de eventos ya no se vuelve a invocar nunca más (a no ser que se registre de nuevo para otro proceso).
Parámetros
type:String — El tipo de evento.
| |
listener:Function — La función del detector que procesa el evento. Esta función debe aceptar un objeto de evento como parámetro único y no debe devolver ningún valor, tal como indica el siguiente ejemplo:
function(evt:Event):void La función puede tener cualquier nombre. | |
useCapture:Boolean (default = false ) —
Determina si el detector funciona en la fase de captura o en las fases de destino y de propagación. Si useCapture se define como true , el detector procesa el evento sólo durante la fase de captura y no en las fases de destino o propagación. Si useCapture es false , el detector procesa el evento sólo durante la fase de destino o de propagación. Para detectar el evento en las tres fases, llame dos veces a addEventListener , una con useCapture establecido en true y, después, otra con useCapture definido como false .
| |
priority:int (default = 0 ) — El nivel de prioridad del detector de eventos. La prioridad viene designada por un entero de 32 bits sin signo. Cuanto mayor sea el número, mayor será la prioridad. Todos los detectores con prioridad n se procesan antes que los detectores con prioridad n-1. Si dos o más detectores comparten la misma prioridad, se procesarán en el orden en el que se añadieron. La prioridad predeterminada es 0.
| |
useWeakReference:Boolean (default = false ) — Determina si la referencia al detector es fuerte o débil. Una referencia fuerte (valor predeterminado) impide que el detector sea eliminado por el recolector de datos innecesarios. Una referencia débil no lo hace. Las funciones de miembros de clase no están sujetas a la recolección de elementos no utilizados, por lo que |
createMessageChannel | () | método |
public function createMessageChannel(receiver:Worker):MessageChannel
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Crea una nueva instancia de MessageChannel para enviar mensajes desde el programa de trabajo en el que se llama al método a otro programa de trabajo receptor. Código del programa de trabajo que crea el objeto MessageChannel que puede utilizar para enviar mensajes unidireccionales al objeto Worker especificado como argumento receiver
.
Aunque se puede utilizar una instancia de MessageChannel para enviar mensajes y datos entre instancias de Worker, es necesario transferir como propiedad compartida al menos una instancia de MessageChannel a un objeto Worker secundario mediante la llamada al método setSharedProperty()
del 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 — El programa de trabajo que recibirá mensajes transmitidos a través del canal de mensajes creado
|
MessageChannel — El objeto MessageChannel creado por la operación
|
getSharedProperty | () | método |
public function getSharedProperty(key:String):*
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Recupera un valor almacenado en este programa de trabajo con una clave determinada.
El código de un programa de trabajo secundario puede llamar a este método para recuperar un valor hasta en el constructor de la clase principal del swf del programa de trabajo.
Parámetros
key:String — Nombre de la propiedad compartida que se va a recuperar
|
* — El valor de propiedad compartida almacenado con la clave especificada, o bien null si no hay ningún valor guardado para la clave especificada
|
removeEventListener | () | método |
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Elimina un detector del objeto EventDispatcher. Si no hay ningún detector coincidente registrado con el objeto EventDispatcher, la llamada a este método no surtirá ningún efecto.
Parámetros
type:String — El tipo de evento.
| |
listener:Function — El objeto detector que se va a eliminar.
| |
useCapture:Boolean (default = false ) —
Especifica si el detector se registró para la fase de captura o para las fases de destino y de propagación. Si el detector se registró tanto para la fase de captura como para las fases de destino y de propagación, se necesitarán dos llamadas a removeEventListener() para eliminar ambos detectores: una llamada con useCapture() definido como true y otra llamada con useCapture() establecido en false .
|
setSharedProperty | () | método |
public function setSharedProperty(key:String, value:*):void
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Proporciona un valor determinado disponible en el código que se ejecuta en el swf del programa de trabajo.
Puede llamar a este método antes de llamar al método start()
del programa de trabajo. En dicho caso, la propiedad compartida estará disponible en el código del swf del programa de trabajo en el momento de la creación.
El valor transferido al parámetro value
puede ser prácticamente cualquier objeto. Salvo las siguientes excepciones, cualquier objeto transferido al parámetro value
no se transmitirá por referencia. Cualquier cambio realizado en el objeto de un programa de trabajo después de llamar a setSharedProperty()
no se transmite al otro programa de trabajo. El objeto se copia mediante su serialización a formato AMF3 y deserializándolo después en un nuevo objeto en el programa de trabajo receptor. Por este motivo, cualquier objeto que no pueda serializarse en formato AMF3, incluidos los objetos de visualización, no se podrán transferir al value parámetro value
. Para que una clase personalizada se pueda transferir correctamente, la definición de la clase debe registrarse con la función flash.net.registerClassAlias()
o los metadatos [RemoteClass]
. Con cualquiera de las dos técnicas, se debe utilizar el mismo alias para ambas versiones del programa de trabajo de la clase.
Existen cinco tipos de objetos que sirven de excepción a la regla que dicta que los objetos no se comparten entre programas de trabajo:
- El programa de trabajo
- MessageChannel
- ByteArray compartible (un objeto ByteArray con su propiedad
shareable
establecida entrue
- Mutex
- Condición
Si transfiere una instancia de estos objetos al parámetro value
, cada programa de trabajo tendrá una referencia al mismo objeto subyacente. Los cambios realizados en la instancia de un programa de trabajo estarán disponibles inmediatamente en los demás programas de trabajo. Además, si transfiere la misma instancia de estos objetos más de una vez con setSharedProperty()
, el motor de ejecución no creará una copia nueva del objeto en el programa de trabajo receptor. En su lugar, se reutilizará la misma referencia para reducir así el uso de memoria del sistema.
Llamar a este método con null
o undefined
como argumento de value
borrará cualquier valor previamente definido para el argumento key
especificado. Limpiar un valor de esta forma elimina su referencia y permite que se elimine como datos innecesarios.
Puede utilizar cualquier valor de String en el argumento key. Estas propiedades compartidas están disponibles para cualquier código que tenga acceso a un programa de trabajo. Para evitar sobrescribir accidentalmente un valor, utilice un prefijo, sufijo o mecanismo similar para que los nombres de las claves sean todos unívocos.
Parámetros
key:String — El nombre con el que se guarda la propiedad compartida.
| |
value:* — El valor de la propiedad compartida.
|
Elementos de API relacionados
start | () | método |
public function start():void
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Inicia la ejecución del programa de trabajo. El motor de ejecución crea el subproceso del programa de trabajo y llama al constructor de la clase principal del swf del programa de trabajo.
Esta operación es asincrónica. Cuando finaliza el arranque del programa de trabajo, cambia su propiedad state
por WorkerState.RUNNING
y distribuye un evento workerState
.
terminate | () | método |
public function terminate():Boolean
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Detiene la ejecución del código de este programa de trabajo. Llamar a este método anula cualquier código ActionScript del swf del programa de trabajo.
Valor devueltoBoolean — true si el código del programa de trabajo se estaba ejecutando y se ha interrumpido, o false si nunca se llegó a iniciar el programa de trabajo
|
workerState | Evento |
flash.events.Event
propiedad Event.type =
flash.events.Event.WORKER_STATE
Versión del lenguaje: | ActionScript 3.0 |
Versiones de motor de ejecución: | Flash Player 11.4, AIR 3.4 |
Se distribuye cuando cambia el valor de la propiedad state
del programa de trabajo.
Event.WORKER_STATE
define el valor de la propiedad type
de un objeto de evento workerState
.
Este evento tiene las propiedades siguientes:
Propiedad | Valor |
---|---|
bubbles | false |
cancelable | false ; no hay ningún comportamiento predeterminado que cancelar. |
currentTarget | Objeto que procesa de forma activa el objeto de evento con un detector de eventos. |
target | El objeto que inició este evento. |
Este ejemplo consta de tres clases de ActionScript: WorkerExample es la clase principal y el programa de trabajo primordial. BackgroundWorker es la clase que lleva a cabo el trabajo en segundo plano. Está compilada como la clase principal del swf del programa de trabajo en segundo plano. CountResult es una clase personalizada que se utiliza para transferir datos entre los dos programas de trabajo como un objeto simple y no como varios valores.
En este ejemplo, el programa de trabajo en segundo plano cuenta en bucle hasta un número especificado por el programa de trabajo principal. A medida que avanza en su trabajo, envía mensajes de progreso al programa de trabajo principal. Por último, cuando finaliza el recuento, el programa de trabajo en segundo plano envía un mensaje al programa de trabajo principal para notificar que ha terminado y el tiempo que ha tardado.
La clase WorkerExample es la clase principal del swf, por lo que también es la clase principal del programa de trabajo primordial. En el método initialize()
, el código crea el objeto del programa de trabajo en segundo plano con los bytes de la clase BackgroundWorker, que están incorporados con una etiqueta [Embed]
.
Después de crear el programa de trabajo en segundo plano mediante la llamada a WorkerDomain.createWorker()
, el código establece la comunicación entre los programas de trabajo. Primero, el código crea un conjunto de objeto MessageChannel. Los transfiere al programa de trabajo en segundo plano mediante una llamada al método setSharedProperty()
. Finalmente, lo registra en el evento workerState
del objeto Worker en segundo plano e inicia el programa de trabajo mediante la llamada a su método start()
.
A medida que el programa de trabajo en segundo plano hace su trabajo, envía mensajes de progreso (y, finalmente, el resultado) al programa de trabajo principal. El programa de trabajo principal utiliza esta información para actualizar la barra de progreso y el 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; } } }
En el método initialize()
, recibe objetos MessageChannel transferidos por el programa de trabajo principal. Se utilizan para la comunicación entre los dos programas de trabajo.
El programa de trabajo principal llama al método send()
en el canal de mensajes commandChannel
para enviar un mensaje. Dentro del programa de trabajo en segundo plano, el motor de ejecución distribuye el evento channelMessage
mediante una llamada al método handleCommandMessage()
.
El trabajo real del programa de trabajo en segundo plano se realiza en el método count()
. A medida que el programa de trabajo en segundo plano avanza con su recuento, envía mensajes de progreso al programa de trabajo principal llamando al método send()
en el objeto MessageChannel de progressChannel
. Cuando termina de contar, llama al método send()
en el objeto MessageChannel de 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()
utilizando el mismo nombre de 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 cargar dinámicamente un SWF remoto que contiene código ActionScript no funciona, el SWF remoto tiene que pasarse al programa de trabajo como SWF sin código. 2. La incorporación de SWF (con código ABC) mediante la etiqueta [Embed] no funciona en iOS. Cada programa de trabajo adicional se crea desde un swf independiente. Para crear una nueva instancia de la clase Worker, transfiera un objeto ByteArray con los bytes del swf del programa de trabajo de segundo plano como argumento del método createWorker()
de la clase WorkerDomain.
Hay dos formas comunes de acceder a los bytes de un SWF para este fin en iOS: La primera manera es utilizar Loader
para cargar un archivo SWF externo y la segunda es utilizar URLLoader
para cargar el archivo SWF.
El siguiente ejemplo utiliza la API Loader
para cargar el archivo 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
, es necesario configurar la comprobación de la propiedad isPrimordial
en el programa de trabajo en segundo plano tal y como se muestra en este ejemplo.
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, 02:12 PM Z