パッケージ | flash.system |
クラス | public final class Worker |
継承 | Worker EventDispatcher Object |
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
ワーカーを使用すると、(メインの swf のワーカーを含む)別のワーカーで別の操作を実行するのと同時に、「バックグラウンドで」コードを実行できます。非ワーカーコンテキストでは、例えば、巨大なデータのループ処理など、一部の処理は実行に時間がかかるので、メインアプリケーションスレッドが十分な速さで画面を更新できなくなります。これにより、画面の途切れやフリーズが発生する可能性があります。
ワーカーを使用すると、長時間の操作や低速な操作をバックグラウンドで実行できます。各ワーカーは、他のワーカーとは別の実行スレッドでコードを実行します。あるワーカーの長時間を要するコードが、別のワーカーのコードの実行をブロックすることはありません。代わりに、コードの 2 つのセットが並行して実行されます。したがって、ワーカーは、メインアプリケーションスレッドで継続して画面を更新しながら、バックグラウンドでコードを実行するのに使用できます。
この複数のコード命令セットを同時に実行する機能は、「並行処理」と呼ばれます。
注意:並列処理のためのワーカーの使用は、Flash Player およびデスクトッププラットフォームの AIR でサポートされます。モバイルプラットフォームについては、並列処理は Android と iOS の両方の AIR でサポートされます。静的 isSupported プロパティを使用して、並行処理を使用する前に、並行処理がサポートされているかどうかをチェックできます。
Worker()
コンストラクターを呼び出して Worker インスタンスを直接作成しないでください。並行処理のためのワーカーの使用がサポートされているコンテキストでは、ランタイムは起動時に自動的にメイン SWF と関連付けられた Worker(「基本ワーカー」と呼ばれる)を作成します。
追加の各ワーカーは、異なる swf から作成されます。Worker クラスの新しいインスタンスを作成するには、バックグラウンドワーカーの swf のバイトを引数とする ByteArray を WorkerDomain クラスの createWorker()
メソッドに渡します。この目的で swf のバイトにアクセスするには、次の 3 つの共通の方法があります。
-
[Embed] メタタグを使用して、.swf ファイルをアプリケーションに 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(); }
-
URLLoader を使用して、外部 SWF ファイルをロードします。
// 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(); }
-
基本ワーカーおよびバックグラウンドワーカーとして単一の swf を使用します。
// 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 } }
複数のワーカーは、それぞれが分離した状態で実行され、同じメモリ、変数、およびコードにはアクセスしません。ただし、Worker インスタンス間でメッセージおよびデータを渡すには、3 つのメカニズムを利用できます。
- 共有プロパティ:各ワーカーには、そのワーカー自体と他のワーカーの両方から設定および読み取り可能な名前付きの値の内部セットがあります。
setSharedProperty()
メソッドを使用して値を設定し、getSharedProperty()
メソッドを使用して値を読み取ることができます。 - MessageChannel:MessageChannel オブジェクトを使用すると、あるワーカーから別のワーカーにメッセージおよびデータを単方向で送信できます。受信ワーカーのコードは、メッセージが到着したら通知されるイベントをリッスンできます。MessageChannel オブジェクトを作成するには、
createMessageChannel()
メソッドを使用します。 - 共有可能 ByteArray:ByteArray オブジェクトの
shareable
プロパティがtrue
の場合、すべてのワーカーにおけるその ByteArray のインスタンスで、基になる同じメモリが使用されます。複数のワーカーのコードで同時に共有メモリにアクセスできるので、コードではByteArray.shareable
プロパティの説明で示したメカニズムを使用して、予期しないデータの変更による問題の発生を防ぐ必要があります。
いくつかのランタイム API は、バックグラウンドワーカーで実行するコードでは使用できません。これらは、主に、ユーザー入出力メカニズム、またはウィンドウやドラッグなどオペレーティングシステムエレメントに関連する API で構成されます。原則として、すべてのコンテキストではサポートされない API には、isSupported
、available
、および同様のプロパティを使用して、その API を使用する前に、バックグラウンドワーカーコンテキストで使用できるかどうかを確認します。
注意:ネイティブエクステンションは、バックグラウンドおよびセカンダリワーカーに対してサポートされません。
ワーカーは、メインレンダリングスレッドが他のコードにブロックされることが原因でフレームレートがドロップする可能性を減らすので、便利です。ただし、ワーカーは追加のシステムメモリおよび CPU の使用を必要とし、これにより、アプリケーション全体のパフォーマンスに影響する可能性があります。各ワーカーはそれぞれ独自のランタイム仮想マシンのインスタンス使用するので、通常のワーカーのオーバーヘッドでさえ大きくなる可能性があります。ワーカーを使用する場合は、すべての対象プラットフォームでコードをテストして、システムへの要求が大きすぎないことを確認します。一般的に、2 つ以上のバックグラウンドワーカーを使用しないようにすることをお勧めします。
詳細
Shawn Blais、AS3 ワーカーの紹介:イメージの処理
Shawn Blais、マルチスレッド物理学:物理エンジン用 AS3 ワーカーユーザーガイド
関連する API エレメント
プロパティ | 定義元 | ||
---|---|---|---|
constructor : Object
指定されたオブジェクトインスタンスのクラスオブジェクトまたはコンストラクター関数への参照です。 | Object | ||
current : Worker [静的] [読み取り専用]
現在のコードを含むワーカーへのアクセスを提供する
| Worker | ||
isPrimordial : Boolean [読み取り専用]
このワーカーが基本ワーカーかどうかを示します。 | Worker | ||
isSupported : Boolean [静的] [読み取り専用]
現在のランタイムコンテキストが同時コード実行で Worker オブジェクトの使用をサポートするかどうかを示します。 | Worker | ||
state : String [読み取り専用]
ライフサイクルにおけるワーカーの現在の状態です。 | Worker |
メソッド | 定義元 | ||
---|---|---|---|
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void [オーバーライド]
イベントリスナーオブジェクトを EventDispatcher オブジェクトに登録し、リスナーがイベントの通知を受け取るようにします。 | Worker | ||
新しい MessageChannel インスタンスを作成して、メソッドが呼び出されたワーカーから別の受信ワーカーにメッセージを送信します。 | Worker | ||
イベントをイベントフローに送出します。 | EventDispatcher | ||
名前付きのキーと共にこのワーカーに格納された値を取得します。 | Worker | ||
EventDispatcher オブジェクトに、特定のイベントタイプに対して登録されたリスナーがあるかどうかを確認します。 | EventDispatcher | ||
オブジェクトに指定されたプロパティが定義されているかどうかを示します。 | Object | ||
Object クラスのインスタンスが、パラメーターとして指定されたオブジェクトのプロトタイプチェーン内にあるかどうかを示します。 | Object | ||
指定されたプロパティが存在し、列挙できるかどうかを示します。 | Object | ||
[オーバーライド]
EventDispatcher オブジェクトからリスナーを削除します。 | Worker | ||
ループ処理に対するダイナミックプロパティの可用性を設定します。 | Object | ||
ワーカーの swf で実行するコードで使用できる名前付きの値を提供します。 | Worker | ||
ワーカーの実行を開始します。 | Worker | ||
このワーカーのコード実行を停止します。 | Worker | ||
ロケール固有の規則に従って書式設定された、このオブジェクトのストリング表現を返します。 | Object | ||
指定されたオブジェクトのストリング表現を返します。 | Object | ||
指定されたオブジェクトのプリミティブな値を返します。 | Object | ||
指定されたイベントタイプについて、この EventDispatcher オブジェクトまたはその祖先にイベントリスナーが登録されているかどうかを確認します。 | EventDispatcher |
イベント | 概要 | 定義元 | ||
---|---|---|---|---|
[ブロードキャストイベント] Flash Player または AIR アプリケーションがオペレーティングシステムのフォーカスを取得して、アクティブになったときに送出されます。 | EventDispatcher | |||
[ブロードキャストイベント] Flash Player または AIR アプリケーションがオペレーティングシステムのフォーカスを失って、非アクティブになったときに送出されます。 | EventDispatcher | |||
ワーカーの state プロパティの値が変更されたときに送出されます。 | Worker |
current | プロパティ |
isPrimordial | プロパティ |
isPrimordial:Boolean
[読み取り専用] 言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
このワーカーが基本ワーカーかどうかを示します。
「基本ワーカー」は、最初の swf が実行中のワーカーです。このワーカーは、画面へのレンダリングを制御します。
このプロパティは、基本ワーカーおよびバックグラウンドワーカーが同じ swf ファイルの 2 つのインスタンスであるアプリケーションを設計するのに使用できます。他には、バックグラウンドワーカーが、基本ワーカーから異なる swf にコンパイルされた異なるコードを使用するようにコードを構築できます。
実装
public function get isPrimordial():Boolean
isSupported | プロパティ |
state | プロパティ |
addEventListener | () | メソッド |
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
イベントリスナーオブジェクトを EventDispatcher オブジェクトに登録し、リスナーがイベントの通知を受け取るようにします。イベントリスナーは、特定のタイプのイベント、段階、および優先度に関する表示リスト内のすべてのノードに登録できます。
イベントリスナーが正常に登録された後に、addEventListener()
をさらに呼び出して優先度を変更することはできません。リスナーの優先度を変更するには、最初に removeListener()
を呼び出す必要があります。その後、同じリスナーを新しい優先度レベルで再度登録できます。
リスナーが登録された後に、addEventListener()
(type
または useCapture
に別の値を設定)を再度呼び出すと、別のリスナー登録が作成されることに注意してください。例えば、最初にリスナーを登録するときに useCapture
を true
に設定すると、そのリスナーはキャプチャ段階のみでリスニングします。同じリスナーオブジェクトを使用して再度 addEventListener()
を呼び出すと(このとき、useCapture
に false
を設定)、異なる 2 つのリスナーが登録されます。1 つはキャプチャ段階でリスニングするリスナーで、もう 1 つはターゲット段階とバブリング段階でリスニングするリスナーです。
ターゲット段階またはバブリング段階のみを対象とするイベントリスナーを登録することはできません。登録時にこれらの段階が組み合わされるのは、バブリングはターゲットノードの祖先にしか適用されないためです。
イベントリスナーが不要になった場合は、removeEventListener()
を呼び出して、イベントリスナーを削除します。削除しない場合、メモリの問題が発生する可能性があります。ガベージコレクションでは、オブジェクトの送出が行われている限り、リスナーを削除しないので、イベントリスナーは自動的には削除されません(useWeakReference
パラメーターが true
に設定されていない場合)。
EventDispatcher インスタンスをコピーしても、それに関連付けられているイベントリスナーはコピーされません。新しく作成したノードにイベントリスナーが必要な場合は、ノードを作成した後に、リスナーを関連付ける必要があります。ただし、EventDispatcher インスタンスを移動した場合は、関連付けられているイベントリスナーも一緒に移動されます。
イベントがノードで処理されるときに、イベントリスナーがそのノードに登録中であれば、イベントリスナーは現在の段階ではトリガーされません。ただし、バブリング段階など、イベントフローの後の段階でトリガーすることができます。
イベントがノードで処理されているときにイベントリスナーがノードから削除された場合でも、イベントは現在のアクションによってトリガーされます。削除された後は、その後の処理で再び登録されない限り、イベントリスナーは二度と呼び出されません。
パラメーター
type:String — イベントのタイプです。
| |
listener:Function — イベントを処理するリスナー関数です。この関数は、次の例のように、Event オブジェクトを唯一のパラメーターとして受け取り、何も返さないものである必要があります。
function(evt:Event):void 関数の名前は任意に付けられます。 | |
useCapture:Boolean (default = false ) —
リスナーが、キャプチャ段階、またはターゲットおよびバブリング段階で動作するかどうかを判断します。useCapture を true に設定すると、リスナーはキャプチャ段階のみでイベントを処理し、ターゲット段階またはバブリング段階では処理しません。useCapture を false に設定すると、リスナーはターゲット段階またはバブリング段階のみでイベントを処理します。3 つの段階すべてでイベントを受け取るには、addEventListener を 2 回呼び出します。useCapture を true に設定して呼び出し、useCapture を false に設定してもう一度呼び出します。
| |
priority:int (default = 0 ) — イベントリスナーの優先度レベルです。優先度は、符号付き 32 bit 整数で指定します。数値が大きくなるほど優先度が高くなります。優先度が n のすべてのリスナーは、優先度が n-1 のリスナーよりも前に処理されます。複数のリスナーに対して同じ優先度が設定されている場合、それらは追加された順番に処理されます。デフォルトの優先度は 0 です。
| |
useWeakReference:Boolean (default = false ) — リスナーへの参照が強参照と弱参照のいずれであるかを判断します。デフォルトである強参照の場合は、リスナーのガベージコレクションが回避されます。弱参照では回避されません。 クラスレベルメンバー関数はガベージコレクションの対象外であるため、クラスレベルメンバー関数の |
createMessageChannel | () | メソッド |
public function createMessageChannel(receiver:Worker):MessageChannel
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
新しい MessageChannel インスタンスを作成して、メソッドが呼び出されたワーカーから別の受信ワーカーにメッセージを送信します。MessageChannel オブジェクトを作成するワーカーのコードは、receiver
引数として指定された Worker オブジェクトへの単方向のメッセージの送信に使用できます。
MessageChannel インスタンスはある Worker インスタンスから別のインスタンスにメッセージおよびデータを送信するのに使用できますが、Worker オブジェクトの setSharedProperty()
メソッドを呼び出すことで、少なくとも 1 つの MessageChannel インスタンスが共有プロパティとして子 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);
パラメーター
receiver:Worker — メッセージを受け取るワーカーは、作成されたメッセージチャンネルで送信される
|
MessageChannel — 操作によって作成された MessageChannel オブジェクト
|
getSharedProperty | () | メソッド |
public function getSharedProperty(key:String):*
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
名前付きのキーと共にこのワーカーに格納された値を取得します。
子ワーカーのコードは、このメソッドを呼び出して、ワーカー swf のメインクラスのコンストラクターにあるのと同じくらい早い値を所得できます。
パラメーター
key:String — 取得する共有プロパティの名前
|
* — 指定されたキーと共に格納された共有プロパティ値、または指定されたキーに値が格納されていない場合は null です。
|
removeEventListener | () | メソッド |
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
EventDispatcher オブジェクトからリスナーを削除します。対応するリスナーが EventDispatcher オブジェクトに登録されていない場合は、このメソッドを呼び出しても効果はありません。
パラメーター
type:String — イベントのタイプです。
| |
listener:Function — 削除するリスナーオブジェクトです。
| |
useCapture:Boolean (default = false ) —
リスナーが、キャプチャ段階、またはターゲットおよびバブリング段階に対して登録されたかどうかを示します。リスナーがキャプチャ段階だけでなくターゲット段階とバブリング段階にも登録されている場合は、removeEventListener() を 2 回呼び出して両方のリスナーを削除する必要があります。1 回は useCapture() を true に設定し、もう 1 回は useCapture() を false に設定する必要があります。
|
setSharedProperty | () | メソッド |
public function setSharedProperty(key:String, value:*):void
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
ワーカーの swf で実行するコードで使用できる名前付きの値を提供します。
ワーカーの start()
メソッドを呼び出す前に、このメソッドを呼び出すことができます。この場合、共有プロパティは、構築時にワーカーの swf のコードで使用できます。
value
パラメーターには、ほとんどすべてのオブジェクトを値として渡すことができます。後述の例外を除いて、value
パラメーターに渡されるすべてのオブジェクトは、参照からは渡されません。setSharedProperty()
が呼び出されてからあるワーカーのオブジェクトに対して行われた変更は、別のワーカーには引き継がれません。オブジェクトを AMF3 フォーマットに直列化し、受信ワーカーの新しいオブジェクトに直列化解除することで、オブジェクトがコピーされます。そのため、表示オブジェクトを含む、AMF3 フォーマットに直列化できないすべてのオブジェクトは、value
パラメーターに渡せません。カスタムクラスが適切に渡されるようにするために、クラス定義は、flash.net.registerClassAlias()
関数または [RemoteClass]
メタデータを使用して登録する必要があります。どちらの方法でも、両方のワーカーのクラスのバージョンに同じエイリアスを使用する必要があります。
オブジェクトはワーカー間で共有されないという規則の例外として、5 つのタイプのオブジェクトがあります。
- Worker
- MessageChannel
- 共有可能 ByteArray(
shareable
プロパティをtrue
に設定した ByteArray オブジェクト) - Mutex
- Condition
これらのオブジェクトのインスタンスを value
パラメーターに渡すと、各ワーカーは、同じ基になるオブジェクトへの参照を持ちます。あるワーカーのインスタンスに対して行われた変更は、別のワーカーで即座に利用できます。また、setSharedProperty()
を使用して 2 回以上それらのオブジェクトの同じインスタンスを渡すと、ランタイムは受信ワーカーにオブジェクトの新しいコピーを作成しません。代わりに、同じ参照が再利用され、システムメモリの使用を減らします。
value
引数に null
または undefined
を指定してこのメソッドを呼び出すと、指定された key
引数に以前設定されていた値をクリアします。この方法で値をクリーンアップすると、値への参照を削除し、ガベージコレクションによって収集できます。
key 引数にすべての String 値を使用できます。これらの共有プロパティは、ワーカーへのアクセスを持つすべてのコードで使用できます。意図しない値の上書きを回避するには、キー名が一意になるようにし、接頭辞、接尾辞、または同様のメカニズムの使用を検討してください。
パラメーター
key:String — 共有プロパティが格納される名前です。
| |
value:* — 共有プロパティの値です。
|
関連する API エレメント
start | () | メソッド |
public function start():void
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
ワーカーの実行を開始します。ランタイムはワーカースレッドを作成し、ワーカー swf のメインクラスのコンストラクターを呼び出します。
この操作は非同期です。ワーカーの起動が完了すると、ワーカーは state
プロパティを WorkerState.RUNNING
に変更し、workerState
イベントを送出します。
terminate | () | メソッド |
workerState | イベント |
flash.events.Event
プロパティ Event.type =
flash.events.Event.WORKER_STATE
言語バージョン: | ActionScript 3.0 |
ランタイムバージョン: | Flash Player 11.4, AIR 3.4 |
ワーカーの state
プロパティの値が変更されたときに送出されます。
Event.WORKER_STATE
定数は、workerState
イベントオブジェクトの type
プロパティの値を定義します。
このイベントには、次のプロパティがあります。
プロパティ | 値 |
---|---|
bubbles | false |
cancelable | false は、キャンセルするデフォルトの動作がないことを示します。 |
currentTarget | イベントリスナーで Event オブジェクトをアクティブに処理しているオブジェクトです。 |
target | このイベントを送出したオブジェクトです。 |
この例は、3 つの ActionScript クラスで構成されています。WorkerExample はメインクラスで、親ワーカーです。BackgroundWorker は、バックグラウンドで動作するクラスです。バックグラウンドワーカー swf のメインクラスとしてコンパイルされます。CountResult は、複数の値でなく単一のオブジェクトとして 2 つのワーカー間でデータを渡すのに使用されるカスタムクラスです。
この例では、バックグラウンドワーカーは親ワーカーによって指定された数までループしてカウントします。作業が進むに従って、進行状況のメッセージを親ワーカーに送信します。最後に、カウントが終了すると、バックグラウンドワーカーは、終了したこととカウントにかかった時間を通知するメッセージを親ワーカーに送信します。
WorkerExample クラスは swf のメインクラスなので、基本ワーカーのメインクラスです。initialize()
メソッドでは、コードは、BackgroundWorker クラスのバイトを使用してバックグラウンドワーカーオブジェクトを作成します。これは、[Embed]
タグを使用して埋め込まれます。
WorkerDomain.createWorker()
を呼び出してバックグラウンドワーカーを作成した後、コードはワーカー間の通信を設定します。最初に、コードは MessageChannel オブジェクトのセットを作成します。setSharedProperty()
メソッドを呼び出して、バックグラウンドワーカーにこれらを渡します。最後に、バックグラウンド Worker オブジェクトの workerState
イベントを登録し、start()
メソッドを呼び出してワーカーを起動します。
バックグラウンドワーカーが作業を進めるに従って、進行状況(および最終結果)のメッセージを親ワーカーに送信します。親ワーカーは、この情報を使用して、プログレスバーとテキストインジケーターを更新します。
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; } } }
initialize()
メソッドで、親ワーカーが渡した MessageChannel オブジェクトを受信します。これらのオブジェクトは、2 つのワーカー間の通信に使用されます。
親ワーカーは commandChannel
メッセージチャンネルに対して send()
メソッドを呼び出して、メッセージを送信します。次に、バックグラウンドワーカー内で、ランタイムが handleCommandMessage()
メソッドを呼び出して channelMessage
イベントを送出します。
バックグラウンドワーカーの実際の作業は、count()
メソッドで行われます。バックグラウンドワーカーがカウントを進めるに従って、progressChannel
MessageChannel オブジェクトに対して send()
メソッドを呼び出して、進行状況のメッセージを親ワーカーに送信します。カウントが終了すると、resultChannel
MessageChannel オブジェクトに対して send()
メソッドを呼び出します。
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()
メソッドを呼び出します。
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. ActionScript コードを含むリモート SWF の動的なロードは動作しないので、リモート SWF は除外された SWF としてワーカーに渡される必要があります。2. [Embed] タグを使用した SWF(ABC コードを持つ)の埋め込みは、iOS では動作しません。追加の各ワーカーは、異なる SWF から作成されます。Worker クラスの新しいインスタンスを作成するには、バックグラウンドワーカーの SWF のバイトを引数とする ByteArray を WorkerDomain クラスの createWorker()
メソッドに渡します。
iOS において、この目的で SWF のバイトにアクセスするには、次の 2 つの共通の方法があります。1 つ目の方法では、Loader
を使用して外部 SWF ファイルをロードします。2 つ目の方法では、URLLoader
を使用して SWF ファイルをロードします。
次の例では、Loader
API を使用して 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
のロード関数が呼び出されている間に実行されるので、この例に示すようにバックグラウンドワーカーの isPrimordial
プロパティをチェックする必要があります。
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, 10:34 AM Z