2009-08-05 10 views
4

私は過去1ヶ月間に自分自身にactionscript 3を教えてきましたが、最近、オブジェクトが削除されたと思った後にオブジェクトが何かをしていたという問題が発生しました。問題はイベントリスナーがデフォルトのuseWeakReference = falseを使用していることが原因であるとわかりました。なぜそれがデフォルトであるのか不思議です。 弱参照を使用しない利点は何ですか?それはなぜデフォルトですか? 一般的には弱い参照を使いたいと思うので、何かが欠けているはずです。AS3のEventListenersで弱参照を使用する利点は何ですか?

おかげで、 -Ted

答えて

2

あなたは正しいですが、一般的に、あなたは弱い参照、時間のおそらく約99%を使用したいです。私は、デフォルト値が本当にtrueに設定されるべきだと思うが、そうでないとそれに対処しなければならない。私はあなたが常に弱い参照を使用する習慣に入ることをお勧めします。いくつかの頭痛を軽減し、ガベージコレクションの管理に役立つようにいくつかのパフォーマンス上の利点を見てください。

だから、あなたはいつそれを偽にしたいですか?基本的には、ガベージコレクタがあなたがもう使用していないと判断したときに、自動的にクリーンアップしたくないときはいつでも。これらの状況はまれであり、その時が来たらあなたはたぶん知っているでしょう。

HOWEVERそれはあなた自身の特定の問題を解決できない場合があります。ガベージコレクタは予測不可能な間隔でのみ実行されるため、オブジェクトへの参照をすべて削除しても、これらのイベントはクリーンアップされるまで処理されます。最善の方法は、イベントリスナーを自分で削除して、再度トリガーされないようにすることです。これは、removeEventListenerメソッドを使用して行うことができます。

幸運、

タイラー。

6

点は、その弱参照が...彼らは高価で遅く、より多くのスペースを消費している...ここにいくつかのベンチマークのコードです:

package { 
    //{ region imports 
     import flash.display.Sprite; 
     import flash.events.Event; 
     import flash.events.EventDispatcher; 
     import flash.system.System; 
     import flash.utils.*; 
    //} endregion 
    public class Main extends Sprite {  
     public function Main():void { 
      switch (0) { 
       case 0: this.benchmarkDispatchers(false); break; 
       case 1: this.benchmarkDispatchers(true); break; 
       case 2: this.benchmarkDictionaries(false); break; 
       case 3: this.benchmarkDictionaries(true); break;   
      } 
     } 
     private function benchmarkDictionaries(weakKeys:Boolean, size:uint = 1000000):void { 
      var a:Array = []; 
      for (var i:int = 0; i < size; i++) 
       a.push({ "foo":i }); 

      var d:Dictionary = new Dictionary(weakKeys); 
      var start:int = getTimer(); 
      var mem0:int = System.totalMemory; 

      for (var j:int = 0; j < size; j++) 
       d[a[j]] = j; 
      trace("adding "+size+" keys took "+(getTimer()-start)+" msecs and "+(System.totalMemory-mem0)+" B of memory with weakKeys == "+weakKeys);       
     } 
     private function benchmarkDispatchers(weakRef:Boolean, size:uint = 100000):void { 
      var a:Array = []; 
      var f:Function = function (i:*):Function { 
       return function():void { i; } 
      } 
      for (var i:int = 0; i < size; i++) 
       a.push(f(i)); 
      var e:EventDispatcher = new EventDispatcher(); 
      var start:int = getTimer(); 
      var mem0:uint = System.totalMemory; 
      for (var j:int = 0; j < size; j++) 
       e.addEventListener("foo", a[j], false, 0, weakRef); 
      trace("adding " + size + " event handlers took " + (getTimer() - start) + " msecs and " + (System.totalMemory - mem0) + " B of memory with weakKeys == " + weakRef); 
     } 
    } 
} 

これは私が私のマシン上で得るものです:

adding 100000 event handlers took 679 msecs and 6922240 B of memory with weakKeys == false 
adding 100000 event handlers took 1348 msecs and 13606912 B of memory with weakKeys == true 
adding 1000000 keys took 283 msecs and 16781312 B of memory with weakKeys == false 
adding 1000000 keys took 906 msecs and 42164224 B of memory with weakKeys == true 

結果は、辞書用もう少し抜本あり、おそらく何のActionScript時間に関する関与の呼び出し、およびがないので、あなたが見ることができるようにイベントハンドラを登録する際に、いくつかのストレージ・オーバーヘッドが(必要なメモリの間の差を少なくするので、 69バイト/ハンドラと16 B ...弱参照を比較するときにyte/key)...

そうです。弱い参照を使用することは、涼しい事実についてではありません。それはあなたのためにリスナーを削除する必要はありませんあなたがスケーラブルなアプリケーションを手に入れたいならば、あなたはこの種のことを自分で行う必要があります.100%の信頼性を望むなら、GCが仕事をすることを望むことはできませんが、あなたは自分でクリーンアップをする必要があります...また、あなたはあなたのアプリで良い階層を持っているなら、おそらく多くの場合、この問題に遭遇することはありません ...意味では、弱い参照なしでは解決できない問題はまれであるため、適切なオブジェクトクリーンアップを行う時間を費やしたくありません...それは怠惰からだけでなく、本当の利点を提供するときに使用する必要があります。虚偽による虚偽...

希望に役立つ希望...;)

greetz非同期操作を行う際にオブジェクトグラフにつながために実行していないものはゴミが任意の時点で収集することができるので

+0

私は 'System.totalMemory'はあなたに正確な結果を与えるためにチェックしないと思います。このプロパティは、Flashプラグインではなく、アプリケーションが使用するメモリによって割り当てられたメモリを返します。 –

2

弱参照は、あなたをかむことができ

back2dos。上記の例では間違って行く二つのものがあります

function weakRefSample() : void 
{ 
    var evntDispatcher : IEventDispatcher = new EventDispatcher(); 

    evntDispatcher.addEventListener(Event.COMPLETE, scopeHandler, false, 0, true); 

    function scopedHandler(event : Event) : void 
    { 
    } 
} 

は特に、機能をスコープしているイベントハンドラの弱参照を使用することはありません

    scopeHandlerを収集することができ
  • そこに理由evntDispatcherを収集することができるように、オブジェクトグラフ
  • 何も存在することを必要としないためweakRefSampleの実行範囲は(何もscopedHandlerを使用していない)を収集することが可能に係留されていません。 evntDispatcherは別の非同期イベントで待機していた場合は、そのイベントが完了する前に、それが収集される可能性があります。
0

弱参照イベントリスナーを持つタイマーインスタンスがイベントを発生させないことがあります。

関連する問題