Flash Player 11.4 i nowsze wersje, Adobe AIR 13.4 i nowsze wersje dla komputerów
Pierwszym krokiem do wprowadzenia współbieżności za pomocą procesu roboczego jest utworzenie procesu roboczego wykonywanego w tle. Do utworzenia procesu roboczego można użyć obiektów dwóch typów. Pierwszym z nich jest tworzone przez użytkownika wystąpienie procesu roboczego. Drugim jest obiekt WorkerDomain, który tworzy proces roboczy oraz zarządza uruchomionymi w aplikacji procesami roboczymi.
Podczas wczytywania środowiska wykonawczego obiekt WorkerDomain jest tworzony automatycznie. Środowisko wykonawcze tworzy także automatycznie proces roboczy dla głównego pliku SWF aplikacji. Pierwszy proces roboczy jest określany jako
pierwotny proces roboczy
.
W aplikacji istnieje tylko jeden obiekt WorkerDomain, dzięki czemu dostęp do jego wystąpienia można uzyskać za pomocą właściwości statycznej
WorkerDomain.current
.
Aby w dowolnym momencie uzyskać dostęp do bieżącego wystąpienia procesu roboczego (tj. procesu, w którym jest wykonywany aktualny kod), można użyć właściwości statycznej
Worker.current
.
Tworzenie procesu roboczego z pliku SWF
Główny plik SWF jest wykonywany w pierwotnym procesie roboczym. Analogicznie proces roboczy działający w tle wykonuje kod jednego pliku SWF. Aby użyć procesu roboczego działającego w tle, należy napisać jego kod i skompilować go do pliku SWF. W celu utworzenia procesu roboczego działającego w tle proces macierzysty musi za pośrednictwem obiektu ByteArray móc uzyskać dostęp do zawartości pliku SWF, który został napisany z przeznaczeniem do pracy w tle. Dany obiekt ByteArray jest przekazywany do metody
createWorker()
obiektu WorkerDomain. Wówczas tworzony jest potomny proces roboczy.
Istnieją trzy sposoby na przekazanie zawartości pliku SWF obiektu działającego w tle w postaci obiektu ByteArrray.
Osadzenie pliku SWF procesu roboczego
Plik SWF procesu roboczego można osadzić w głównym pliku SWF za pomocą metaznacznika [Embed]:
[Embed(source="../swfs/BgWorker.swf", mimeType="application/octet-stream")]
private static var BgWorker_ByteClass:Class;
private function createWorker():void
{
var workerBytes:ByteArray = new BgWorker_ByteClass();
var bgWorker:Worker = WorkerDomain.current.createWorker(workerBytes);
// ... set up worker communication and start the worker
}
Plik SWF procesu roboczego jest kompilowany do głównego pliku SWF jako podklasa klasy ByteArray o nazwie BgWorker_ByteClass. Utworzenie wystąpienia tej klasy pozwala na uzyskanie obiektu ByteArray uzupełnionego o zawartość bajtową pliku SWF procesu roboczego.
Wczytanie zewnętrznego pliku SWF procesu roboczego
Obiekt URLLoader pozwala na wczytanie zewnętrznego pliku SWF. Dany plik SWF musi pochodzić z tej samej domeny zabezpieczeń. Może to być na przykład plik SWF wczytany z tej samej domeny internetowej co główny plik SWF lub plik uwzględniony w pakiecie aplikacji AIR.
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);
// ... set up worker communication and start the worker
}
Gdy obiekt URLLoader zakończy wczytywanie pliku SWF, jego zawartość bajtowa będzie dostępna we właściwości
data
obiektu URLLoader (na przykład jako
zdarzenie.cel.data
).
Użycie głównego pliku SWF jako pliku SWF procesu roboczego
Jeden plik SWF może pełnić jednocześnie funkcje głównego pliku SWF oraz pliku procesu roboczego. Dostęp do zawartości bajtowej pliku SWF można uzyskać za pomocą właściwości
loaderInfo.bytes
głównej klasy wyświetlania.
// 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 or the background worker
if (Worker.current.isPrimordial)
{
// create a background worker
var bgWorker:Worker = WorkerDomain.current.createWorker(swfBytes);
// ... set up worker communication and start the worker
}
else // entry point for the background worker
{
// set up communication between workers using getSharedProperty()
// ... (not shown)
// start the background work
}
}
Użycie tego rozwiązania wymaga zastosowania wyrażenia
if
w celu rozgałęzienia kodu pliku SWF w ramach konstruktora klasy głównej lub metody wywoływanej przez ten konstruktor. Aby określić, w którym procesie roboczym jest wykonywany kod, należy użyć właściwości
isPrimordial
procesu roboczego, zgodnie z przykładowym kodem.
Rozpoczynanie wykonywania procesu roboczego
Aby po utworzeniu procesu roboczego rozpocząć wykonywanie jego kodu, należy wywołać metodę
start()
procesu roboczego. Metoda
start()
nie jest wykonywana natychmiast. Aby sprawdzić, kiedy proces roboczy zostanie uruchomiony, należy zarejestrować detektor zdarzenia
workerState
procesu roboczego. Zdarzenie to jest wywoływane, gdy w procesie roboczym jest przełączany stan cyklu roboczego, na przykład przy rozpoczęciu wykonywania kodu. W module obsługi zdarzeń
workerState
należy sprawdzić, czy właściwość
state
procesu roboczego ma wartość
WorkerState.RUNNING
. Jeśli tak, to proces roboczy jest uruchomiony, a konstruktor klasy głównej został wywołany. Poniższy kod jest przykładem rejestracji detektora zdarzenia
workerState
i wywoływania metody
start()
:
// 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();
private function workerStateHandler(event:Event):void
{
if (bgWorker.state == WorkerState.RUNNING)
{
// The worker is running.
// Send it a message or wait for a response.
}
}
Zarządzanie wykonywaniem procesu roboczego
Dostęp do uruchomionych procesów roboczych można uzyskać w dowolnym momencie za pomocą metody
listWorkers()
klasy WorkerDomain. Jej wynikiem jest zestaw procesów roboczych (w tym procesu pierwotnego), w których właściwość
state
ma wartość
WorkerState.RUNNING
. Procesy robocze, które nie zostały uruchomione lub których wykonywanie zostało wstrzymane, nie zostaną uwzględnione w wyniku zwracanym przez tę metodę.
Jeśli proces roboczy nie jest już potrzebny, można wywołać jego metodę
terminate()
. Pozwoli to na wyłączenie procesu roboczego oraz zwolnienie pamięci i innych zasobów systemowych, które były przez niego używane.
|
|
|