Kommunicera mellan arbetare

Flash Player 11.4 och senare, Adobe AIR 13.4 och senare för datorplattformar

Trots att arbetare kör respektive kod i separata huvudprogram så vore det ingen fördel om de var fullständigt isolerade från varandra. Kommunikationen mellan arbetare innebär i sista hand att data skickas mellan dem. Det finns tre metoder för att hämta data från en arbetare och skicka dem till en annan.

När du ska avgöra vilken av dessa datadelningstekniker som är lämpligast för att skicka vissa data ska du beakta de två viktigaste skillnaderna. En skillnad mellan dem är om det är en händelse som ska meddela mottagaren om att nya data är tillgängliga eller om det är den mottagande arbetaren som ska kontrollera om det finns uppdateringar. En annan skillnad mellan dessa datadelningstekniker har att göra med hur data de facto skickas. I vissa fall erhåller den mottagande arbetaren en kopia av delade data, vilket innebär att fler objekt skapas och att mer minnesutrymme och processorkapacitet krävs. I vissa fall erhåller arbetarna objekt som refererar till samma underliggande systemminne, vilket innebär att färre objekt skapas och i ett generellt mindre minnesutnyttjande. Dessa skillnader beskrivs här:

Kommunikationsteknik

Skickar händelse när data erhålls

Delar minne mellan arbetare

Delade egenskaper mellan arbetare

Nej

Nej, objekt kopieras inte referenser

MessageChannel

Ja

Nej, objekt kopieras inte referenser

Delbar ByteArray

Nej

Ja, minnet delas

Skicka data med en delad egenskap

Det enklaste sättet att dela data mellan arbetare är att använda en delad egenskap. Varje arbetare underhåller en intern ordlista med delade egenskapsvärden. Dessa egenskaper är lagrade med strängnyckelnamn för att skilja dem från egenskaper. Om du vill lagra ett objekt i en arbetare som en delad egenskap anropar du Worker-objektets setSharedProperty() -metod med två argument, nyckelnamnet och värdet som ska lagras:

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

När den delade egenskapen är inställd kan värdet läsas genom ett anrop av Worker-objektets getSharedProperty() -metod, skickat i nyckelnamnet:

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

Det finns inga restriktioner för vilken arbetare som läser eller ställer in egenskapsvärdet. Koden i bakgrundsarbetaren kan till exempel anropa dess setSharedProperty() -metod för att dela ett värde. Kod som körs i den överordnade arbetaren kan sedan använda getSharedProperty() för att hämta data.

Värdet som skickas till metoden setSharedProperty() kan näst intill vara alla typer av objekt. När du anropar metoden getSharedProperty() är det objekt som returneras en kopia av objektet som skickades till setSharedProperty() och inte en referens till samma objekt. Detta gäller med några få undantag. I Delade referenser och kopierade värden förklaras mer ingående hur data delas.

Den största fördelen med att använda en delad egenskap för att skicka data mellan arbetare är att den är tillgänglig även innan arbetaren körs. Du kan anropa Worker-objektets setSharedProperty() -metod i bakgrunden för att ställa in en delad egenskap även innan arbetaren körs. När den överordnade arbetaren anropar arbetarens start() -metod, kommer den underordnade arbetarens huvudklasskonstruktor att anropas. Eventuella delade egenskaper som ställdes in innan start() anropades är tillgängliga för kod som kan läsas i den underordnade arbetaren.

Skicka data med MessageChannel

En meddelandekanel är en envägslänk för att skicka data mellan två arbetare. Det finns en viktig fördel med att använda ett MessageChannel-objekt för att skicka data mellan arbetare. När du skickar ett meddelande (ett objekt) med en meddelandekanal kommer MessageChannel-objektet att skicka en channelMessage -händelse. Kod i den mottagande arbetaren kan avlyssna den händelsen för att veta när data är tillgängligt. Detta innebär att den mottagande arbetaren inte kontinuerligt behöver kontrollera om det finns datauppdateringar.

En meddelandekanal är associerad med endast två arbetare, en avsändare och en mottagare. Om du vill skapa ett MessageChannel-objekt, anropar du Worker-objektets createMessageChannel() -metod, genom att skicka den mottagande arbetaren som ett argument:

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

Båda arbetarna måste ha åtkomst till MessageChannel-objektet. Det enklaste sättet att göra detta att skicka MessageChannel-objektet med metoden setSharedProperty() :

receivingWorker.setSharedProperty("incomingChannel", sendChannel);

Registrera i den mottagande arbetaren en avlyssnare för MessageChannel-objektets channelMessage -händelse. Denna händelse skickas när den avsändande arbetaren skickar data genom meddelandekanalen.

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

För att faktiskt kunna skicka data ska du i den avsändande arbetaren anropa MessageChannel-objektets send() metod:

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

I den mottagande arbetaren anropar MessageChannel händelsehanteraren för channelMessage . Den mottagande arbetaren kan sedan hämta data genom att anropa MessageChannel-objektets receive() -metod.

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

Objektet som returneras av metoden receive har samma datatyp som objektet som skickas till metoden send() . Det mottagna objektet är en kopia av objektet som skickades av avsändaren och inte en referens till objektet i den avsändande arbetaren, såvida det inte tillhör någon av de få datatyperna som beskrivs i Delade referenser och kopierade värden .

Dela data med en delbar ByteArray

När ett objekt skickas mellan två arbetare erhåller den mottagande arbetaren ett nytt objekt som är en kopia av originalet. De båda objekten är lagrade på olika platser i systemets minne. Detta innebär att varje kopia av objektet som erhålls ökar den totala minneskapaciteten som används under körningen. Dessutom så innebär det att varje ändring som du gör i ett objekt i en arbetare inte påverkar kopian i den andra arbetaren. Mer information om hur data kopieras finns i Delade referenser och kopierade värden .

Standard är att samma beteende används för ett ByteArray-objekt. Om du skickar en ByteArray-instans till en setSharedProperty() -metod för ett Worker-objekt eller till en send() -metod för ett MessageChannel-objekt, skapas under körningen en ny ByteArray i datorns minne och den mottagande arbetaren erhåller en ByteArray-instans som är en referens till den nya ByteArray-instansen. Du kan emellertid ändra detta beteende för ett ByteArray-objekt genom att ange att shareable -egenskapen ska vara true .

När ett delbart ByteArray-objekt skickas från en arbetare till en annan, är ByteArray-instansen i den mottagande arbetaren en referens till samma underliggande systemminne som används för ByteArray-instansen i den avsändande arbetaren. När koden för en arbetare ändrar innehållet för bytearrayen kommer dessa ändringar omedelbart att vara tillgängliga i andra arbetare som har åtkomst till den delade bytearrayen.

Eftersom koden för arbetarna körs samtidigt är det möjligt för två arbetare att få åtkomst till samma byte i en bytearray samtidigt. Detta kan leda till dataförluster och andra fel. Det finns flera API:er som du kan använda för att hantera åtkomsten till delade resurser och undvika dessa problem.

I klassen ByteArray finns metoder för att validera och ändra bytearrayens innehåll med en enskild operation:

Dessutom innehåller flash.concurrent-paketet klasser som erbjuder åtkomstkontroll för att arbeta med delade resurser:

Delade referenser och kopierade värden

I normalfallet när du anropar Worker.setSharedProperty() eller MessageChannel.send() , har objektet som skickas till den mottagande arbetaren ett serialiserat AMF-format. Detta får vissa konsekvenser:

  • Objektet som skapats i den mottagande arbetaren när dess getSharedProperty() -metod anropas kommer att avserialiseras från AMF-byte. Det är en kopia av originalobjektet och inte en referens till objektet. Ändringar som görs i objektet i någon av arbetarna ändras inte i kopian hos den andra arbetaren.

  • Objekt som inte kan serialiseras i AMF-format såsom visningsobjekt, kan inte skickas till en arbetare med Worker.setSharedProperty() eller MessageChannel.send() .

  • För att en anpassad klass ska kunna avserialiseras måste klassdefinitionen registreras med flash.net.registerClassAlias() -funktionen eller med [RemoteClass] -metadata. Samma alias måste användas för båda arbetarnas versioner av klassen.

Det finns fem specialobjekt som verkligen delas, och inte kopieras, mellan arbetare:

  • Worker-objekten

  • MessageChannel-objekten

  • delbar bytearray (ett ByteArray-objekt vars shareable -egenskap är true )

  • Mutex-objekt

  • Condition-objekt

När du skickar en instans av dessa objekt med Worker.setSharedProperty() - eller MessageChannel.send() -metoden får varje arbetare en referens till samma underliggande objekt. Ändringar gjorda i en instans i en arbetare är omedelbart tillgängliga i en annan arbetare. Om du dessutom skickar samma instans av dessa objekt till en arbetare mer än en gång, kommer ingen ny kopia av objektet att skapas i den mottagande arbetarens miljö. I stället kommer samma referens att återanvändas.

Fler datadelningstekniker

Förutom arbetarspecifika metoder för att skicka data, kan arbetare även utbyta data genom att använda någon av de befintliga API:erna som har stöd för att dela data mellan två swf-program, som exempelvis följande:

  • lokalt delade objekt

  • skriva data i en fil för en arbetare och läsa från filen i den andra arbetaren

  • lagra data i och läsa data från en SQLite-databas

När du delar en resurs mellan två eller flera arbetare bör du vanligtvis undvika att låta flera arbetare få åtkomst till resursen samtidigt. Om du till exempel låter flera arbetare få åtkomst till en fil i ett lokalt filsystem kan detta medföra dataförluster eller fel, och det kanske inte heller stöds i operativsystemet.

Om du vill skydda dig mot samtidiga åtkomstproblem ska du använda klasserna Mutex och Condition i flash.concurrent-paketet för att få kontrollen över detta när du arbetar med delade resutser.

Till skillnad från andra datadelningsmetoder är SQLite-databasmotorn framtagen för samtidig åtkomst och den har ett eget internt stöd för transaktioner. Flera arbetare kan samtidigt använda en SQLite-databas utan risk för att förstöra några data. Eftersom arbetarna använder olika SQLConnection-instanser får varje arbetare åtkomst till databasen via en separat transaktion. Samtidiga datahanteringsoperationer påverkar inte dataintegriteten.

Se även

Arbeta med lokala SQL-databaser i AIR

flash.concurrent paket