Archive for 2009/7/8

addEventListenerの最後の引数にはuseWeakReferenceというオプションがあり、これをtrueにするとメモリリークが発生しにくいということですが、デフォルトではこれはfalse。つまり、自分で参照はすべて制御するというものです。

しかし、これをデフォルトでtrueにしましょう!とオライリーの本などでも書いてあったので、そうしてみるか。と書いてみたら、思い通り動かない!という状況になってしまいました。

そんなソースを紹介します。

package  {

 import flash.events.*;
 import flash.utils.*;
 import flash.net.*;

 public class SMTPConn {

  private var sock:Socket;

  //  弱参照を使うか、強参照を使うか?
  private var useWeakReference:Boolean = true;

  public function SMTPConn() {
   sock = new Socket();

  }

  public function connect():void{

   sock.addEventListener(Event.CONNECT,connectHandler,false,0,useWeakReference);
   sock.addEventListener(ProgressEvent.SOCKET_DATA,readBytes,false,0,useWeakReference);
   sock.connect("127.0.0.1",25);
   trace("open ...");
  }

  private function connectHandler(e:Event):void{
   trace("connected ...");
  }

  private function readBytes(e:ProgressEvent):void{
   trace("read bytes " + sock.bytesAvailable);
   trace(sock.readUTFBytes(sock.bytesAvailable));
  }
 }
}

具体的には、Socketで接続が完了してもconnectHandlerが動かないのです。
実は、上のソース自体には別に問題がありません。
このクラスの呼び方というか、オブジェクトのスコープにあるのだとおもいます。
(理屈的にも、動作的にもそのようなうごきになったので)

このソースをあるボタンを押したときのclick="test_smtp()"のような感じで以下のようにしました。

private function test_smtp():void{
  var smtp:SMTPConn = new SMTPConn();
  smtp.connect();
}

このソースが、うまくうごくときと動かないときがあるのです。
最初、相当なやみましたが、スコープの問題だとわかりました。

たぶん、connectHandlerが動く前に、test_smtp()内の処理が終了し、smtpオブジェクトがいらなくなったので、ガベージ対象になったのでしょう。
これで、弱参照をつかっているとconnectHandlerが動かないと。

ただし、useWeakReference = false にしたり、smtpのオブジェクトのスコープを1つうえ。つまり、

var smtp:SMTPConn;
private function test_smtp():void{
  smtp = new SMTPConn();
  smtp.connect();
}

のようにすればうまく動きます。
UIがあれば、さすがにそのUIが消えた時点でほとんどの処理が必要なくなり、このようなことは発生するケースが思い浮かびませんが、バックグラウンドで処理する場合にはこのような使い方がありえるのではないかなと。

あらためて、addEventListenerの勉強というか、強参照と弱参照の勉強をさせてもらいました。

RSS
Add to Google

カスタム検索
ソフトウェア&ライブラリ


ライブラリ
airxmail(en)
AIR版メール送受信ライブラリ
airxzip
AIR版ZIP圧縮・解凍ライブラリ
カレンダー
2009年7月
« 6月   8月 »
 12345
6789101112
13141516171819
20212223242526
2728293031  
アーカイブ
カテゴリ
にほんブログ村 IT技術ブログへ