Communication entre programmes de travail

Flash Player 11.4 et les versions ultérieures, Adobe AIR 13.4 et les versions ultérieures pour les plates-formes de bureau

Bien que les programmes de travail exécutent leur code dans des threads d’exécution distincts, ils n’auraient aucun intérêt s’ils étaient totalement isolés les uns des autres. La communication entre les programmes de travail signifie principalement échanger des données. Il existe trois mécanismes principaux pour transmettre des données d’un programme de travail à un autre.

Au moment de choisir la technique de partage la mieux adaptée à vos besoins de transmission de données, tenez compte des éléments qui les différencient. La première différence entre ces techniques est de savoir s’il existe un événement informant le récepteur que de nouvelles données sont disponibles ou si le programme de travail de réception doit rechercher les mises à jour. La deuxième différence entre ces techniques de partage de données porte sur la méthode de transmission des données. Dans certains cas, le programme de travail de réception obtient une copie des données partagées, ce qui implique la création de davantage d’objets, et donc une plus grande utilisation de la mémoire et du processeur. Dans d’autres cas, les programmes de travail accèdent aux objets faisant référence à la même mémoire système sous-jacente, ce qui implique la création de moins d’objets, et donc une plus faible utilisation de la mémoire. Ces différences sont précisées ici :

Technique de communication

Distribution de l’événement à la réception des données

Partage de la mémoire entre programmes de travail

Propriétés partagées entre programmes de travail

Non

Non, les objets sont des copies et non des références

MessageChannel

Oui

Non, les objets sont des copies et non des références

Objet ByteArray partageable

Non

Oui, la mémoire est partagée

Transmission de données avec une propriété partagée

La méthode la plus simple pour partager des données entre programmes de travail est d’utiliser une propriété partagée. Chaque programme de travail conserve un dictionnaire interne de valeurs de propriété partagée. Pour distinguer les propriétés entre elles, celles-ci sont enregistrées avec des noms de clés de type chaîne. Pour enregistrer un objet sur un programme de travail en tant que propriété partagée, appelez la méthode setSharedProperty() de l’objet Worker avec deux arguments, le nom de clé et la valeur à enregistrer :

// code running in the parent worker 
bgWorker.setSharedProperty("sharedPropertyName", someObject);

Une fois la propriété partagée définie, il est possible de lire la valeur en appelant la méthode getSharedProperty() de l’objet Worker en transmettant le nom de clé :

// code running in the background worker 
receivedProperty = Worker.current.getSharedProperty("sharedPropertyName");

N’importe quel programme de travail peut lire ou définir la valeur de la propriété. Par exemple, le code dans un programme de travail en arrière-plan peut appeler sa méthode setSharedProperty() pour enregistrer une valeur. Le code qui s’exécute dans le programme de travail parent peut alors faire appel à la propriété getSharedProperty() pour recevoir les données.

Pratiquement tout type d’objet peut être transmis comme valeur à la méthode setSharedProperty() . Lorsque vous appelez la méthode getSharedProperty() , l’objet renvoyé est une copie de l’objet transmis à la méthode setSharedProperty() et non une référence au même objet, sauf dans quelques cas isolés. La méthode de partage des données est expliquée en détails à la section Références partagées et valeurs copiées .

Le principal avantage d’utiliser une propriété partagée pour transmettre des données entre programmes de travail est que celle-ci est disponible même avant que le programme de travail ne commence à s’exécuter. Vous pouvez appeler la méthode setSharedProperty() d’un objet de programme de travail en arrière-plan pour définir une propriété partagée, même avant que le programme de travail ne commence à s’exécuter. Lorsque le programme de travail parent appelle la méthode start() de l’objet Worker, le moteur d’exécution appelle le constructeur de la classe principale du programme de travail enfant. Toutes les propriétés partagées définies avant l’appel de la méthode start() sont disponibles dans le code afin que le programme de travail enfant puisse les lire.

Transmission de données via un canal de message

Un canal de message fournit un lien de transmission de données unidirectionnel entre deux programmes de travail. L’utilisation d’un objet MessageChannel pour transmettre des données entre programmes de travail présente un avantage majeur. Lorsque vous envoyez un message (un objet) à l’aide d’un canal de message, l’objet MessageChannel distribue un événement channelMessage . Le code dans le programme de travail de réception peut écouter cet événement pour savoir quand les données seront disponibles. De cette façon, le programme de travail de réception n’a pas besoin de rechercher continuellement des mises à jour de données.

Un canal de message est associé à deux programmes de travail uniquement : un programme de travail d’envoi et un programme de travail de réception. Pour créer un objet MessageChannel, appelez la méthode createMessageChannel() de l’objet Worker d’envoi, en transmettant le programme de travail de réception en tant qu’argument :

// In the sending worker swf 
var sendChannel:MessageChannel; 
sendChannel = Worker.current.createMessageChannel(receivingWorker);

Les deux programmes de travail doivent avoir accès à l’objet MessageChannel. La méthode la plus simple pour effectuer cette opération est de transmettre l’objet MessageChannel à l’aide de la méthode setSharedProperty() :

receivingWorker.setSharedProperty("incomingChannel", sendChannel);

Dans le programme de travail de réception, enregistrez un écouteur pour l’événement channelMessage de l’objet MessageChannel. Cet événement est distribué lorsque le programme de travail d’envoi envoie les données via le canal de message.

// In the receiving worker swf 
var incomingChannel:MessageChannel; 
incomingChannel = Worker.current.getSharedProperty("incomingChannel"); 
incomingChannel.addEventListener(Event.CHANNEL_MESSAGE, handleIncomingMessage);

Pour envoyer les données, appelez la méthode send() de l’objet MessageChannel dans le programme de travail d’envoi :

// In the sending worker swf 
sendChannel.send("This is a message");

Dans le programme de travail de réception, l’objet MessageChannel appelle l’écouteur d’événement channelMessage . Le programme de travail de réception peut alors obtenir les données en appelant la méthode receive() de l’objet MessageChannel.

private function handleIncomingMessage(event:Event):void 
{ 
    var message:String = incomingChannel.receive() as String; 
}

L’objet renvoyé par la méthode de réception possède le même type de données que l’objet transmis dans la méthode send() . L’objet reçu est une copie de l’objet transmis par le programme de travail d’envoi et non une référence à l’objet dans le programme de travail de réception, à moins qu’il ne soit de l’un des types de données pris en charge, comme décrit à la section Références partagées et valeurs copiées .

Partage de données avec un objet ByteArray partageable

Lors de la transmission d’un objet entre deux programmes de travail, le programme de travail de réception obtient un nouvel objet, qui est une copie de l’objet original. Ces deux objets sont stockés à divers emplacements dans la mémoire du système. Chaque copie de l’objet qui est reçue augmente donc la mémoire totale utilisée par le moteur d’exécution. Par ailleurs, les modifications apportées à un objet dans un programme de travail ne sont pas appliquées à la copie dans l’autre programme de travail. Pour plus d’informations sur la méthode de copie des objets, voir Références partagées et valeurs copiées .

Par défaut, un objet ByteArray se comporte de la même façon. Si vous transmettez une occurrence de ByteArray à la méthode setSharedProperty() de l’objet Worker ou à la méthode send() de l’objet MessageChannel, le moteur d’exécution crée un nouvel objet ByteArray dans la mémoire de l’ordinateur et le programme de travail de réception obtient une occurrence de ByteArray qui est une référence au nouvel objet ByteArray. Vous pouvez néanmoins changer ce comportement pour un objet ByteArray en définissant sa propriété shareable sur true .

Lorsqu’un objet ByteArray partageable est transmis d’un programme de travail à un autre, l’occurrence de ByteArray dans le programme de travail de réception est une référence à la même mémoire système sous-jacente utilisée par l’occurrence de ByteArray dans le programme de travail d’envoi. Lorsque le code d’un programme de travail modifie le contenu du tableau d’octets, ces modifications sont immédiatement disponibles dans d’autres programmes de travail ayant accès à ce tableau d’octets partagé.

Etant donné que les programmes de travail exécutent leur code simultanément, deux programmes de travail peuvent tenter d’accéder en même temps aux mêmes octets dans un tableau d’octets, ce qui pourrait entraîner la perte ou la corruption des données. Vous pouvez utiliser plusieurs API pour gérer l’accès aux ressources partagées et éviter ces problèmes.

La classe ByteArray dispose de méthodes vous permettant de valider et de modifier le contenu du tableau d’octets en une seule opération :

En outre, le package flash.concurrent inclut des classes qui permettent de contrôler l’accès aux ressources partagées :

Références partagées et valeurs copiées

En temps normal, lorsque vous appelez la méthode Worker.setSharedProperty() ou la méthode MessageChannel.send() , l’objet transmis au programme de travail de réception est transmis par sérialisation au format AMF. Cela entraîne certaines conséquences :

  • L’objet créé dans le programme de travail de réception lors de l’appel de sa méthode getSharedProperty() est désérialisé des octets AMF. Il est une copie de l’objet original et non une référence à l’objet. Toute modification apportée à l’objet dans l’un des programmes de travail n’est pas appliquée à la copie dans l’autre programme de travail.

  • Les objets qu’il est impossible de sérialiser au format AMF, notamment les objets d’affichage, ne peuvent pas être transmis à un programme de travail qui utilise Worker.setSharedProperty() ou MessageChannel.send() .

  • Pour désérialiser 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] . Le même alias doit être utilisé pour les deux versions du programme de travail de la classe .

Il existe cinq types d’objets véritablement partagés au lieu d’être copiés entre programmes de travail :

  • Objets Worker

  • Objets MessageChannel

  • Tableau d’octets partageable (objet ByteArray dont la propriété shareable est définie sur true )

  • Objets Mutex

  • Objets Condition

Lorsque vous transmettez une occurrence de l’un de ces objets à l’aide de la méthode Worker.setSharedProperty() ou de la méthode MessageChannel.send() , 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 sont immédiatement disponibles dans les autres programmes de travail. En outre, si vous transmettez plusieurs fois la même occurrence de l’un de ces objets à un programme de travail, 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.

Autres techniques de partage de données

Outre les mécanismes de transmission de données propres aux programmes de travail, les programmes de travail peuvent également échanger des données à l’aide de l’une des API existantes prenant en charge le partage de données entre deux applications swf :

  • objets partagés locaux

  • écriture de données sur un fichier dans un programme de travail et lecture du fichier dans un autre programme de travail

  • stockage et lecture de données à partir d’une base de données SQLite

Lorsque vous partagez une ressource entre deux ou plusieurs programmes de travail, vous devez généralement éviter que divers programmes de travail accèdent en même temps à cette ressource. Par exemple, si plusieurs programmes de travail accèdent à un fichier sur le système de fichiers local, vous risquez de perdre ou d’endommager les données ; en outre, le système d’exploitation risque de ne pas prendre en charge cette opération.

Pour éviter les problèmes liés aux accès simultanés, utilisez les classes Mutex et Condition du package flash.concurrent pour contrôler l’accès aux ressources partagées.

Contrairement à d’autres mécanismes de partage de données, le moteur de la base de données SQLite est conçu pour un accès simultané et possède un processus transactionnel propre. Plusieurs programmes de travail peuvent accéder à une base de données SQLite sans risquer d’endommager les données. Etant donné que les programmes de travail utilisent différentes occurrences de SQLConnection, chaque programme de travail accède à la base de données dans une transaction distincte. Les opérations de manipulation simultanée de données n’ont aucune incidence sur l’intégrité des données.

Voir aussi

Utilisation des bases de données SQL locales dans AIR

Package flash.concurrent