AS3Threadを試してみたよ。
AS3でのコーディングスタイルが全然定まらないで、 かなりヤキモキしている訳なのですが、 BeInteractive! さんの スレッドによる非同期処理はこんな感じ にインスパイアされて 早速 AS3Thread を試してみたよ!
使い方は至って簡単。 Snippets - Spark project の サンプル を見れば分かると思うのですが、 Thread なクラスを継承して、 以下のメソッドを必要に応じてオーバーライドしていく。
- initialize ... 初期化時に一度だけ呼ばれる。
- execute ... ロジックを実行する。
- catchError ... エラーがあった場合に呼ばれる。
- finalize ... 後片付け。terminateした後に一度だけ呼ばれる。
- toString ... 誰か分かるように。オーバーライドしないと親の名前になる。
なので、基本形はこんな感じになる。
package
{
import org.libspark.thread.Thread;
public class ExampleThread extends Thread
{
protected override function initialize():void
{
// 初期化コードを書く。
}
protected override function execute():void
{
// 実際のロジックを書く。
}
protected override function finalize():void
{
// 後片付けコードを書く。
}
public override function toString():void
{
// スレッドの名前を返す。
return '[ExampleThread]';
}
}
}
で、実際にガリガリ書いてみたのですが、 かなり非同期部分を隠蔽出来るよ! デフォルトで LoaderThread なクラスや URLLoaderThread なクラスが用意されてるので、 すぐに試して感動出来たりします! こういうの、ホントにありがたい。
で、何も気にせずコードを書いていたんですが、 ちょっとしたところで壁にブチ当たった。
最初の一連の作業が終わった後、 クリックでSpriteを消してやろうと思って、 それをスレッドにして作ってたんですが、 イベントを受け取ったタイミングで begin しても動かない。 ってか、エラー吐いちゃうよ?なハプニングに遭遇。
一人コードリーディング祭りの結果、 スレッドの処理内じゃないと begin 出来ないっぽい。 begin の中身を見てみるとこうなってて、
// Thread.as@98行目あたり
public function begin():void
{
if (isRunning) {
return;
}
// ココでエラー吐く。
(_parent = _currentThread).addChild(this);
_runHandler = execute;
_executeHandler = beginHandler;
}
null的なやつがどうの。ってエラー吐く。 この _currentThread ってプロパティがnull以外の時しか begin 出来ない事になる訳ですが、 そうなるタイミングってのが、探した限りだと internalExecute の中の処理が走る時だけ。
// Thread.as@208行目あたり
internal function internalExecute():void
{
// ちょっと省略
try {
_currentThread = this; // ココで自分を入れる。
_executeHandler.apply(this);
}
catch (e2:Error) {
handleError(e2);
}
finally {
_currentThread = null; // 処理が終わればnullになる。
}
}
疑似スレッドがゆえに、「スレッドの外」が存在してるのかぁ。 とか、勝手に理解(合ってるかは不明)。 yossy さんとかはどうやって実装してるんだろ? ものっすごい気になる。 強引にでもスレッドの中に処理を持って行くのかな? うーん、それって果たしてどうなんだろう。
でも、ここで終わらないのが スルー力 の無さ! 「スレッドの外」って事は、「メインスレッド上の出来事である。」として、ソースを書き換えてみる。 メインスレッドのインスタンスは MasterThread なクラスが保持しているので、 まずはそれを Thread から参照出来るようにする。
Index: MasterThread.as
===================================================================
--- MasterThread.as (revision 259)
+++ MasterThread.as (working copy)
@@ -11,9 +11,14 @@
_debugView = debugView;
}
- private var _main:Thread;
+ private static var _main:Thread;
private var _debugView:Sprite;
+ internal static function get main():Thread
+ {
+ return _main;
+ }
+
public function executeActiveThreads():void
{
internalExecute();
これで同一パッケージ内からメインスレッドのインスタンスが参照出来るようになった。
次に、エラー吐いてたところで、 _currentThread がnullだった場合、 メインスレッドを渡してやるようにする。
Index: Thread.as
===================================================================
--- Thread.as (revision 259)
+++ Thread.as (working copy)
@@ -101,7 +101,7 @@
return;
}
- (_parent = _currentThread).addChild(this);
+ (_parent = (_currentThread||MasterThread.main)).addChild(this);
_runHandler = execute;
_executeHandler = beginHandler;
これで _currentThread がnullの場合はメインスレッドを使ってスレッドが起動される。
こうする事で、スレッドの処理の外で begin された場合はメインスレッドにぶら下がる形で実行されるよ。 って言っても、実はこれも完璧ではなくて、リスクもちゃんと認識しております。 ちょうど良いタイミングで begin しちゃって、 _currentThread がnullじゃなかったら、問答無用で全然関係ないスレッドにぶら下がります。 が、それを認識した上で、それでもこうあるべきじゃ?って思ってます(実装ではなく挙動として)。 実装はコミッターの方々が、もっと洗練された形でやってのけてくれる事に期待大!
この話題、どこかで yossy さんにあったら是非とも聞いてみたい!
ps. もうちょっと詳しい使い方はリクエストがあれば書いたり書かなかったり。
- Posted at:
- 2008/02/27 03:13:57
- 0 Comments
- 0 TrackBacks
- Tags:
- ActionScript
- Flash
- Thread
- Trackback:
- http://humming.via-kitchen.com/2008/02/27/tried-using-thread-on-as3/trackback/
TrackBacks
まだ登録されていません。
Comments
まだ登録されていません。