Package | flash.system |
Classe | public final class Worker |
Héritage | Worker EventDispatcher Object |
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Un programme de travail permet d’exécuter du code en arrière-plan tandis que d’autres opérations sont en cours d’exécution sur un autre programme de travail (notamment le programme de travail du fichier swf principal). Dans un contexte sans programme de travail, certaines opérations, notamment le traitement d’un grand jeu de données dans une boucle, sont tellement lentes à s’exécuter qu’elles empêchent le thread de l’application principale de mettre à jour l’écran rapidement, ce qui peut entraîner son blocage.
L’utilisation d’un programme de travail permet d’exécuter en arrière-plan des opérations longues ou lentes. Chaque programme de travail exécute son propre code dans un thread d’exécution distinct des autres programmes de travail. Le code long à s’exécuter dans un programme de travail n’empêche pas un autre programme de travail de s’exécuter. Les deux ensembles de code s’exécutent en parallèle. Il est par conséquent possible d’utiliser un programme de travail pour exécuter le code en arrière-plan tout en libérant le thread de l’application principale, qui peut continuer à mettre à jour l’écran.
Cette fonction, qui permet d’exécuter plusieurs ensembles d’instructions de code en même temps, est connue sous le nom de simultanéité.
Remarque : l’utilisation de programmes de travail à des fins de simultanéité est prise en charge dans Flash Player et AIR sur les plateformes de bureau. Pour les plateformes mobiles, la simultanéité est prise en charge dans AIR sous Android et iOS. Vous pouvez faire appel à la propriété statique isSupported pour vérifier si la simultanéité est prise en charge avant d’essayer de l’utiliser.
Vous ne pouvez pas créer d’occurrences de l’objet Worker directement en appelant le constructeur Worker()
. Dans les contextes où l’utilisation de programmes de travail à des fins de simultanéité est prise en charge, le moteur d’exécution crée automatiquement au démarrage l’objet Worker associé au fichier SWF principal, connu sous le nom de programme de travail primordial.
Chaque travail supplémentaire est créé à partir d’un objet SWF distinct. Pour créer une nouvelle occurrence de la classe Worker, transmettez un objet ByteArray avec les octets du fichier swf du programme de travail en arrière-plan en tant qu’argument à la méthode createWorker()
de la classe WorkerDomain. Il existe trois méthodes standard pour accéder aux octets d’un fichier swf à ces fins :
-
Utilisez la métabalise [Embed] pour intégrer le fichier .swf à l’application en tant qu’objet 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(); }
-
Chargez un fichier SWF externe à l’aide d’un objet 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(); }
-
Utilisez un fichier swf unique en tant que programme de travail primordial et programme de travail en arrière-plan :
// 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 } }
Les programmes de travail s’exécutent indépendamment les uns des autres et ne partagent pas la même mémoire, les mêmes variables ni le même code. Il existe néanmoins trois mécanismes pour transmettre des messages et des données entre plusieurs occurrences de l’objet Worker :
- Propriétés partagées : chaque programme de travail dispose d’un ensemble interne de valeurs nommées qu’il est possible de définir et de lire depuis le programme de travail lui-même et depuis d’autres programmes de travail. Vous pouvez définir une valeur à l’aide de la méthode
setSharedProperty()
et lire une valeur à l’aide de la méthodegetSharedProperty()
. - Canal de message : un objet MessageChannel permet d’envoyer des messages et des données d’un programme de travail à un autre en mode unidirectionnel. Le code du programme de travail de réception peut écouter un événement afin d’être informé de l’arrivée d’un message. Pour créer un objet MessageChannel, utilisez la méthode
createMessageChannel()
. - ByteArray partageable : si la propriété
shareable
d’un objet ByteArray est définie surtrue
, la même mémoire sous-jacente est utilisée pour les occurrences de cet objet ByteArray dans tous les programmes de travail. Etant donné que le code de plusieurs programmes de travail peut à tout moment accéder à la mémoire partagée, votre code doit utiliser les mécanismes présentés dans la description de la propriétéByteArray.shareable
pour éviter les problèmes dus à des modifications de donnés inattendues.
Certaines API du moteur d’exécution ne sont pas disponibles dans le code qui s’exécute dans un programme de travail d’arrière-plan. Il s’agit principalement d’API associées à la saisie utilisateur et aux mécanismes de sortie, ou à des éléments du système d’exploitation, tels que les fenêtres et le glissement. En règle générale, pour toute API qui n’est pas prise en charge dans ces contextes, faites appel aux propriétés isSupported
, available
et similaires pour vérifier si l’API est disponible dans le contexte du programme de travail en arrière-plan avant d’essayer de l’utiliser.
Remarque : les extensions natives ne sont pas prises en charge pour les programmes de travail secondaires et en arrière-plan.
Les programmes de travail sont utiles, car ils diminuent le risque d’une baisse de la cadence, qui peut se produire si le thread de rendu principal est bloqué par l’exécution d’un autre code. Les programmes de travail augmentent toutefois l’utilisation de la mémoire système et du processeur, ce qui peut avoir une incidence considérable sur les performances globales de l’application. Etant donné que chaque programme de travail utilise sa propre occurrence de la machine virtuelle du moteur d’exécution, le traitement d’un programme de travail, aussi simple soit-il, peut consommer de nombreuses ressources. Lorsque vous utilisez des programmes de travail, testez votre code sur toutes vos plates-formes cibles afin de vous assurer que les ressources requises ne sont pas trop importantes. Adobe vous recommande de ne pas utiliser plus de deux programmes de travail dans un scénario type.
Plus d’exemples
Création et gestion de programmes de travail
Informations complémentaires
Intro to AS3 Workers: Image Processing, par Shawn Blais (disponible en anglais uniquement)
Multithreaded Physics: Using AS3 Workers for a physics engine, par Shawn Blais (disponible en anglais uniquement)
Eléments de l’API associés
Propriété | Défini par | ||
---|---|---|---|
constructor : Object
Référence à l’objet de classe ou à la fonction constructeur d’une occurrence donnée d’un objet. | Object | ||
current : Worker [statique] [lecture seule]
Fournit un accès au programme de travail qui contient le code actuel
| Worker | ||
isPrimordial : Boolean [lecture seule]
Indique si ce programme de travail est le programme de travail primordial. | Worker | ||
isSupported : Boolean [statique] [lecture seule]
Indique si le contexte du moteur d’exécution actuel prend en charge l’utilisation des objets Worker pour l’exécution de code simultanée. | Worker | ||
state : String [lecture seule]
L’état actuel du programme de travail et son cycle de vie. | Worker |
Méthode | Défini par | ||
---|---|---|---|
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void [override]
Enregistre un objet écouteur d’événement auprès d’un objet EventDispatcher afin que l’écouteur soit averti d’un événement. | Worker | ||
Crée une nouvelle occurrence de l’objet MessageChannel pour envoyer des messages à partir du programme de travail sur lequel la méthode est appelée vers un autre programme de travail récepteur. | Worker | ||
Distribue un événement dans le flux d’événements. | EventDispatcher | ||
Extrait une valeur stockée dans ce programme de travail avec une clé nommée. | Worker | ||
Vérifie si des écouteurs sont enregistrés auprès de l’objet EventDispatcher pour un type spécifique d’événement. | EventDispatcher | ||
Indique si la propriété spécifiée d’un objet est définie. | Object | ||
Indique si une occurrence de la classe Object figure dans la chaîne de prototype de l’objet spécifié en tant que paramètre. | Object | ||
Indique si la propriété spécifiée existe et est énumérable. | Object | ||
[override]
Supprime un écouteur de l’objet EventDispatcher. | Worker | ||
Définit la disponibilité d’une propriété dynamique pour les opérations en boucle. | Object | ||
Fournit une valeur nommée disponible pour le code s’exécutant dans le fichier swf du programme de travail. | Worker | ||
Lance l’exécution du programme de travail. | Worker | ||
Arrête l’exécution du code de ce programme de travail. | Worker | ||
Renvoie la représentation de chaîne de cet objet, formatée selon les paramètres régionaux en vigueur. | Object | ||
Renvoie la représentation sous forme de chaîne de l’objet spécifié. | Object | ||
Renvoie la valeur primitive de l’objet spécifié. | Object | ||
Vérifie si un écouteur d’événement est enregistré auprès de cet objet EventDispatcher ou de ses ancêtres pour le type d’événement spécifié. | EventDispatcher |
Evénement | Synthèse | Défini par | ||
---|---|---|---|---|
[Evénement de diffusion] Distribué lorsque l’application Flash Player obtient le focus du système d’exploitation et devient active. | EventDispatcher | |||
[Evénement de diffusion] Distribué lorsque l’application Flash Player ou AIR perd le focus du système d’exploitation et devient inactive. | EventDispatcher | |||
Distribué lorsque la valeur de la propriété state du programme de travail change. | Worker |
current | propriété |
isPrimordial | propriété |
isPrimordial:Boolean
[lecture seule] Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Indique si ce programme de travail est le programme de travail primordial.
Le programme de travail primordial est le programme de travail dans lequel s’exécute le fichier swf initial. Ce programme de travail contrôle le rendu sur l’écran.
Il est possible d’utiliser cette propriété pour concevoir une application dans laquelle le programme de travail primordial et le programme de travail en arrière-plan sont deux occurrences du même fichier swf. Il est par ailleurs possible de structurer votre code afin que le programme de travail en arrière-plan utilise un code différent compilé sur un fichier swf différent de celui du programme de travail primordial.
Implémentation
public function get isPrimordial():Boolean
isSupported | propriété |
isSupported:Boolean
[lecture seule] Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Indique si le contexte du moteur d’exécution actuel prend en charge l’utilisation des objets Worker pour l’exécution de code simultanée.
Si la fonction de simultanéité est disponible, la valeur de cette propriété est true
.
Implémentation
public static function get isSupported():Boolean
state | propriété |
state:String
[lecture seule] Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
L’état actuel du programme de travail et son cycle de vie. Les valeurs possibles de cette propriété sont définies dans la classe WorkerState.
Implémentation
public function get state():String
Eléments de l’API associés
addEventListener | () | méthode |
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Enregistre un objet écouteur d’événement auprès d’un objet EventDispatcher afin que l’écouteur soit averti d’un événement. Vous pouvez enregistrer les écouteurs d’événement dans tous les nœuds de la liste d’affichage pour un type spécifique d’événement, de phase et de priorité.
Après l’enregistrement d’un écouteur d’événement, vous ne pouvez plus modifier sa priorité par d’autres appels de addEventListener()
. Pour modifier la priorité d’un écouteur, vous devez d’abord appeler removeListener()
. Vous pouvez ensuite réenregistrer l’écouteur avec le nouveau niveau de priorité.
N’oubliez pas qu’une fois l’écouteur enregistré, tous les prochains appels de addEventListener()
avec une valeur type
ou useCapture
différente entraîneront la création d’un autre enregistrement d’écouteur. Si, par exemple, vous enregistrez un écouteur dans lequel la propriété useCapture
est définie sur true
, il écoute uniquement pendant la phase de capture. Si vous appelez addEventListener()
à l’aide du même objet écouteur, mais en définissant useCapture
sur false
, vous obtenez deux écouteurs distincts : l’un qui écoute pendant la phase de capture et l’autre qui écoute pendant les phases cible et de propagation vers le haut (bubbling).
Il est impossible d’enregistrer un écouteur d’événement uniquement pour la phase cible ou la phase de propagation vers le haut. Ces deux phases sont associées pendant l’enregistrement car la propagation vers le haut s’applique uniquement aux ancêtres du nœud cible.
Si vous n’avez plus besoin d’un écouteur d’événements, supprimez-le en appelant removeEventListener()
, afin d’éviter tout problème de mémoire. Les écouteurs d’événement ne sont pas automatiquement supprimés de la mémoire, car le nettoyeur de mémoire ne supprime pas l’écouteur tant que l’objet de distribution existe (à moins que le paramètre useWeakReference
ne soit défini sur true
).
Lors de la copie d’une occurrence d’EventDispatcher, les écouteurs d’événement qui lui sont associés ne sont pas pris en compte (si le nouveau nœud nécessite un écouteur d’événement, vous devez associer celui-ci après la création du nœud). Toutefois, si vous déplacez une occurrence d’EventDispatcher, les écouteurs d’événement qui lui sont associés la suivent.
Si un écouteur d’événement est enregistré sur un nœud alors qu’un événement est en cours de traitement sur ce nœud, l’écouteur n’est pas déclenché pendant la phase actuelle, mais il peut l’être pendant une phase ultérieure du flux d’événements, telle que la phase de propagation vers le haut (bubbling).
Si un écouteur d’événement est supprimé d’un nœud sur lequel un événement est en cours de traitement, il est cependant déclenché par les actions en cours. Une fois supprimé, l’écouteur d’événement n’est plus jamais appelé (à moins d’être réenregistré à des fins de traitement ultérieur).
Paramètres
type:String — Type d’événement.
| |
listener:Function — Fonction d’auditeur qui traite l’événement. Cette fonction doit accepter un objet Event comme paramètre unique et ne rien renvoyer, comme illustré ci-dessous :
function(evt:Event):void Le nom de cette fonction n’a aucune importance. | |
useCapture:Boolean (default = false ) —
Détermine si l’écouteur est actif pendant la phase de capture ou pendant les phases cible et de propagation. Si la propriété useCapture est définie sur true , l’écouteur traite l’événement uniquement pendant la phase de capture et non pendant les phases cible et de propagation. Si la propriété useCapture est définie sur false , l’écouteur traite l’événement uniquement pendant les phases cible et de propagation. Pour écouter l’événement dans les trois phases, appelez addEventListener à deux reprises, une première fois en définissant useCapture sur true , puis une nouvelle fois en définissant useCapture sur false .
| |
priority:int (default = 0 ) — Niveau de priorité de l’écouteur d’événement. La priorité est indiquée par un entier signé de 32 bits. Plus le nombre est élevé, plus la priorité est élevée. Tous les écouteurs dont la priorité correspond à n sont traités avant les écouteurs dotés de la priorité n -1. Les écouteurs dont la priorité est identique sont traités dans l’ordre où ils ont été ajoutés. La priorité par défaut est 0.
| |
useWeakReference:Boolean (default = false ) — Détermine si la référence à l’écouteur est forte ou faible. Une référence forte (valeur par défaut) empêche le nettoyage de votre écouteur, Cela n’est pas le cas avec une référence faible. Les fonctions de membres de niveau classe n’étant pas soumises au nettoyage, vous pouvez définir |
createMessageChannel | () | méthode |
public function createMessageChannel(receiver:Worker):MessageChannel
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Crée une nouvelle occurrence de l’objet MessageChannel pour envoyer des messages à partir du programme de travail sur lequel la méthode est appelée vers un autre programme de travail récepteur. Le code dans le programme de travail qui crée l’objet MessageChannel peut utiliser ce dernier pour envoyer des messages unidirectionnels à l’objet Worker spécifié dans l’argument receiver
.
Bien qu’il soit possible d’utiliser une occurrence de l’objet MessageChannel pour envoyer des messages et des données d’une occurrence de Worker à une autre, au moins une occurrence de l’objet MessageChannel doit être transmise à un objet Worker enfant en tant que propriété partagée en appelant la méthode setSharedProperty()
de l’objet 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);
Paramètres
receiver:Worker — Le programme de travail qui recevra les messages transmis via le canal de message créé
|
MessageChannel — L’objet MessageChannel créé par cette opération
|
getSharedProperty | () | méthode |
public function getSharedProperty(key:String):*
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Extrait une valeur stockée dans ce programme de travail avec une clé nommée.
Le code dans un programme de travail enfant peut appeler cette méthode pour extraire une valeur dans le constructeur de la classe principale du fichier swf du programme de travail.
Paramètres
key:String — Nom de la propriété partagée à extraire
|
* — La valeur de la propriété partagée stockée avec la clé spécifiée, ou null si aucune valeur n’est stockée pour la clé spécifiée
|
removeEventListener | () | méthode |
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Supprime un écouteur de l’objet EventDispatcher. Si aucun écouteur correspondant n’est enregistré auprès de l’objet EventDispatcher, l’appel de cette méthode n’a aucun effet.
Paramètres
type:String — Type d’événement.
| |
listener:Function — Objet écouteur à supprimer.
| |
useCapture:Boolean (default = false ) —
Détermine si l’écouteur a été enregistré pendant la phase de capture ou pendant les phases cible et de propagation. Si l’écouteur a été enregistré pendant la phase de capture et pendant les phases cible et de propagation, il est nécessaire d’appeler removeEventListener() à deux reprises pour le supprimer. Appelez useCapture() une première fois en la définissant sur true , puis une seconde fois useCapture() en la définissant sur false .
|
setSharedProperty | () | méthode |
public function setSharedProperty(key:String, value:*):void
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Fournit une valeur nommée disponible pour le code s’exécutant dans le fichier swf du programme de travail.
Vous pouvez appeler cette méthode avant d’appeler la méthode start()
du programme de travail. Dans ce cas, la propriété partagée est disponible dans le code du fichier swf du programme de travail au moment de la construction.
N’importe quel objet peut être transmis comme valeur au paramètre value
. Sauf dans les cas exceptionnels décrits ci-dessous, tous les objets transmis au paramètre value
ne sont pas transmis par référence. Les modifications apportées à l’objet dans un programme de travail après l’appel de la méthode setSharedProperty()
ne sont pas appliquées à l’autre programme de travail. L’objet est copié en le sérialisant au format AMF3 et en le désérialisant en nouvel objet dans le programme de travail de réception. Pour cette raison, les objets qu’il est impossible de sérialiser au format AMF3, notamment les objets d’affichage, ne peuvent pas être transmis au paramètre value
. Pour transmettre correctement une classe personnalisée, la définition de classe doit être enregistrée avec la fonction flash.net.registerClassAlias()
ou les métadonnées [RemoteClass]
. Quelle que soit la technique choisie, le même alias doit être utilisé pour les deux versions du programme de travail de la classe .
Il existe cinq types d’objets qui échappent à la règle selon laquelle les objets ne sont pas partagés entre les programmes de travail :
- Worker
- MessageChannel
- ByteArray partageable (objet ByteArray dont la propriété
shareable
est définie surtrue
) - Mutex
- Condition
Si vous transmettez une occurrence de ces objets au paramètre value
, chaque programme de travail possède une référence au même objet sous-jacent. Les modifications apportées à une occurrence dans un programme de travail (worker) sont immédiatement disponibles dans les autres programmes de travail. En outre, si vous transmettez plusieurs fois la même occurrence de ces objets à l’aide de la méthode setSharedProperty()
, le moteur d’exécution ne crée par une nouvelle copie de l’objet dans le programme de travail de réception. Au lieu de cela, la même référence est réutilisée afin de réduire l’utilisation de la mémoire système.
Si vous appelez cette méthode en définissant la valeur null
ou undefined
pour l’argument value
, toutes les valeurs précédemment définies pour l’argument key
spécifié sont effacées. Effacer une valeur de cette façon supprime également sa référence, ce qui permet de la nettoyer.
Vous pouvez utiliser n’importe quelle valeur de chaîne dans l’argument key. Ces propriétés partagées sont disponibles aux codes ayant accès à un programme de travail. Pour éviter la suppression accidentelle d’une valeur, pensez à utiliser un préfixe, un suffixe ou un mécanisme similaire pour tenter de créer des noms de clé uniques.
Paramètres
key:String — Nom sous lequel la propriété partagée est stockée.
| |
value:* — Valeur de la propriété partagée.
|
Eléments de l’API associés
start | () | méthode |
public function start():void
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Lance l’exécution du programme de travail. Le moteur d’exécution crée le thread du programme de travail et appelle le constructeur de la classe principale du fichier swf du programme de travail.
Cette opération est asynchrone. Après avoir démarré, le programme de travail change sa propriété state
en propriété WorkerState.RUNNING
et distribue un événement workerState
.
terminate | () | méthode |
public function terminate():Boolean
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Arrête l’exécution du code de ce programme de travail. L’appel de cette méthode annule tout code ActionScript dans le fichier swf du programme de travail.
Valeur renvoyéeBoolean — true si le code dans le programme de travail était en cours d’exécution et a été interrompu, false si le programme de travail n’a jamais démarré
|
workerState | Evénement |
flash.events.Event
propriété Event.type =
flash.events.Event.WORKER_STATE
Version du langage: | ActionScript 3.0 |
Versions du moteur d’exécution: | Flash Player 11.4, AIR 3.4 |
Distribué lorsque la valeur de la propriété state
du programme de travail change.
Event.WORKER_STATE
définit la valeur de la propriété type
d’un objet d’événement workerState
.
Les propriétés de cet événement sont les suivantes :
Propriété | Valeur |
---|---|
bubbles | false |
cancelable | false ; il n’existe aucun comportement par défaut à annuler. |
currentTarget | L’objet qui traite activement l’objet Event avec un écouteur d’événements. |
target | Objet ayant distribué l’événement this. |
Cet exemple comprend les trois classes ActionScript suivantes : WorkerExample est la classe principale et le programme de travail parent. BackgroundWorker est la classe qui effectue les tâches en arrière-plan. Elle est compilée comme classe principale du fichier swf de programme de travail en arrière-plan. CountResult est une classe personnalisée qui permet de transmettre des données entre les deux programmes de travail sous forme d’objet unique et non en tant que valeurs multiples.
Dans cet exemple, le programme de travail en arrière-plan effectue un décompte en boucle jusqu’à atteindre le numéro spécifié par le programme de travail parent. Au fur et à mesure qu’il exécute ses tâches, il envoie des messages de progression au programme de travail parent. Enfin, lorsque le décompte est terminé, le programme de travail en arrière-plan envoie un message au programme de travail parent pour l’informer qu’il a terminé et lui indiquer la durée du décompte.
La classe WorkerExample est la classe principale du fichier swf ; elle est donc la classe principale du programme de travail primordial. Dans la méthode initialize()
, le code crée l’objet de programme de travail en arrière-plan à l’aide des octets de la classe BackgroundWorker, intégrés à l’aide de la balise [Embed]
.
Après la création du programme de travail en arrière-plan à l’aide la méthode WorkerDomain.createWorker()
, le code établit la communication entre les programmes de travail. Le code crée tout d’abord une série d’objets MessageChannel. Il les transmet ensuite au programme de travail en arrière-plan en appelant la méthode setSharedProperty()
. Il s’enregistre enfin pour l’événement workerState
de l’objet Worker en arrière-plan et lance le programme de travail en appelant sa méthode start()
.
Lorsque le programme de travail en arrière-plan effectue ses tâches, il envoie des messages de progression (et, le cas échéant, des messages de résultats) au programme de travail parent. Le programme de travail parent utilise ces informations pour mettre à jour la barre de progression et l’indicateur de texte.
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; } } }
Dans la méthode initialize()
, il reçoit les objets MessageChannel que le programme de travail parent a transmis. Ceux-ci sont utilisés pour établir la communication entre les deux programmes de travail.
Le programme de travail parent appelle la méthode send()
sur le canal de message commandChannel
pour envoyer un message. A l’intérieur du programme de travail en arrière-plan, le moteur d’exécution distribue alors l’événement channelMessage
en appelant la méthode handleCommandMessage()
.
Les tâches actuelles du programme de travail en arrière-plan sont réalisées dans la méthode count()
. A mesure que le programme de travail en arrière-plan poursuit son décompte, il envoie des messages de progression au programme de travail parent en appelant la méthode send()
sur l’objet de message de canal progressChannel
. Lorsqu’il finit de compter, il appelle la méthode send()
sur l’objet de message de canal 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()
à l’aide du même nom d’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. Puisque charger dynamiquement un fichier SWF distant contenant du code ActionScript ne fonctionne pas, le fichier SWF distant doit être transmis au programme de travail en tant que fichier SWF démuni. 2. Intégrer des fichiers SWF (comportant du code ABC) à l'aide de la balise [Embed] ne fonctionnera pas sous iOS. Chaque programme de travail supplémentaire est créé en tant que fichier SWF séparé. Pour créer une nouvelle instance de la classe Worker, transmettez un tableau ByteArray avec les octets du fichier SWF du programme de travail d'arrière-plan en tant qu'argument à la méthode createWorker()
de la classe WorkerDomain.
Il existe deux méthodes standard pour accéder aux octets d'un fichier SWF dans ce but sous iOS : La première méthode consiste à utiliserLoader
pour charger un fichier SWF externe et la seconde à utiliser URLLoader
pour charger le fichier SWF.
L'exemple suivant utilise l'API Loader
pour charger le fichier 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
est appelée, le contrôle de la propriété isPrimordial
doit être placé au niveau du programme de travail, comme indiqué dans cet exemple.
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, 09:30 AM Z