Tworzenie procesów roboczych i zarządzanie nimi

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.