SSブログ

ActionScript Worker (Flash Player マルチスレッド) [Flex]

Flash Builder4.7+Apache Flex4.9+FP11.4でマルチスレッドを試してみた。

Music Playerのスペクトラムイコライザーの計算部分を別スレッドにしてみた。

スクリーンショット 2013-02-17 12.00.38.png

Flash BuilderでまずFlexプロジェクトを作成する。
次にファイル−新規−ActionScriptワーカで子スレッド用クラスを作成する。
このときに子スレッドとのやり取りするWorkersクラスが自動で作成される。

こちらが子スレッドとして動作するMuWorkerクラス
package info.akiboi.worker
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.system.MessageChannel;
	import flash.system.Worker;
                                 :	
	public class MuWorker extends Sprite
	{
		private var commandChannel:MessageChannel;
		private var resultChannel:MessageChannel;
		private var _snd:SoundData;
		public function MuWorker()
		{
			super();
			initialize();
		}
		
		private function initialize():void
		{
			// 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);
			resultChannel = Worker.current.getSharedProperty("resultChannel") as MessageChannel;
                                 :	
		}        
		private function handleCommandMessage(event:Event):void
		{
			if (!commandChannel.messageAvailable)
				return;
			//Objectでメインスレッドからのメッセージを受け取とる
			var obj:Object = commandChannel.receive() as Object;
        //子スレッド処理
                                 :	
        //子スレッド処理終了したらメインスレッドにメッセージを送る
       result:Object = new Object();
                                 :	                 
			resultChannel.send(result);
			}
		}
	}
}


上記子スレッドのクラスを作成すると以下のWorkersクラスファイルが作成されます。
必要な処理を追記します。

package 
{
	
	import flash.events.Event;
	import flash.system.MessageChannel;
	import flash.system.Worker;
	import flash.system.WorkerDomain;
	import flash.system.WorkerState;
                                 :		
	public class Workers
	{
		private var bgWorker:Worker;
		private var bgWorkerCommandChannel:MessageChannel;
		private var resultChannel:MessageChannel;
		
                                 :	
		public function Workers() {
			initialize();
		}

		//子スレッド、メッセージのチャンネル作成して子スレッド起動
		private function initialize():void
		{
			// Register the alias so we can pass CountResult objects between workers
			
			// Create the background worker
			bgWorker = WorkerDomain.current.createWorker(info_akiboi_worker_MuWorker);
			
			// Set up the MessageChannels for communication between workers
			bgWorkerCommandChannel = Worker.current.createMessageChannel(bgWorker);
			bgWorker.setSharedProperty("incomingCommandChannel", bgWorkerCommandChannel);
			
			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();
		}
		
     //メインタスクからの子スレッドにメッセージ送信するメソッド`
     // Main -> Workders -> 子レッド
		public function sendMessage(obj:Object):void
		{
			bgWorkerCommandChannel.send(obj);
		}
		
     //子スレッドのステータスをリスナしておきここで受け取る
		private function handleBGWorkerStateChange(event:Event):void
		{
			if (bgWorker.state == WorkerState.RUNNING) 
			{
        //例 子スレッドが準備できたことをカスタムdispatcherでMainに通知している例
				_dispatcher.muWorkerAPI(EventConst.WORKER_READY,"",true,null);
			}
		}
		
               //子スレッドからメッセージが送信されたら行う処理
		private function handleResultMessage(e:Event):void
		{
        //子スレッドからresultChannelを通して結果を受け取る。
			var result:Object = resultChannel.receive() ;

          //例 子スレッドから結果をカスタムdispatcherを使ってMainに返す
			_dispatcher.muWorkerAPI(result.action,result.msg,result.err,result.obj);
		}
		
     //FBでActionScriptワーカクラスを作成するとこのWorkersクラスが自動作成され、以下のようなマッピング情報が書き込まれます。
		[Embed(source="../workerswfs/info/akiboi/worker/MuWorker.swf", mimeType="application/octet-stream")]
		private static var info_akiboi_worker_MuWorker_ByteClass:Class;
		public static function get info_akiboi_worker_MuWorker():ByteArray
		{
			return new info_akiboi_worker_MuWorker_ByteClass();
		}
		
	}
}

あとは、必要な処理をメインクラスにWorkersクラスをコントロールする処理を追加。

コンパイルは、オプションに-swf-version=17を追加してコンパイル。

子スレッドで他にいくつか処理をやってみたが使えるものが限定されるもよう。
サーバとのやり取りをすると今まで出なかったクロスドメインセキュリティの
エラーがでてしまう。

コントロールできるサーバはcrossdomain.xmlを作成して対処したが
YouTube APIはcrossdomain.xmlが読めてもAPIが拒否されてしまう。
もうちょとよく見ないと・・・

単純な負荷がかかる計算処理などは子スレッドに任せるのはできそう。
あとは通信系が子スレッドにもっていけるといいのになぁ

今回はActionScriptマルチスレッドの仕様よくみないでヘルプのサンプルみて作成。
シリアライズとかJavaでのスレッド鉄則の7パターンでのクラス作成みたいなことは
考えないで単純なやり方で実装。
マルチスレッドは非同期なので乱用は注意しないとね。

Youtube Player 'Mu' Home Page リニューアル [Muse]

Adobe Creative Cloudサービスに入ったので、早速アプリをダウンロード

'Mu'なるアイコンがある。'Mu'とはちょっと気になる。
Adobe[レジスタードトレードマーク] Muse[トレードマーク]のこと。'Muse'は、デザイナーはコードを記述することなく、デスクトップやモバイルデバイス向けのHTML Webサイトを作成することができるらしい。

ということで、今週末、'Youtube Player 'Mu' のホームページをこの'Muse'を使ってリニューアルして見た。
丸一日かかったが、とりあえずこれでアップすることにした。

home.png

htmlで書いたほうが早いようなこともあったが、まずは、イメージ通りに作成することができた。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。