トップ回答者
Event メモリの開放について

質問
-
以下のコードを実行すると、メモリが増えていきます。
開放する方法が見当たらないのですが・・
Public Class TestClass0
Shared Sub main()
For i As Integer = 1 To 100000
Dim t As New TestClass1
If i Mod 10000 = 0 Then
Debug.WriteLine(GC.GetTotalMemory(True))
End If
t = Nothing
Next
End Sub
End ClassPublic Class TestClass1
Public Event TestEvent As EventHandler ' <-- ここ
Sub New()
End Sub
End Class
すべての返信
-
-
えーと、すみません。
質問の意図が明確ではありませんでした。TestClass1で
Public Event TestEvent As EventHandler
をコメントして、コードを実行し
GC.GetTotalMemory(True)
で、メモリ使用量を表示した場合
431860
490768
490660
490648
490660
490648
490660
490648
490660
490648となり、メモリが開放されているのが確認できますが
Public Event TestEvent As EventHandler
を有効にして、実行した場合
719756
1096920
1163500
1574548
1854536
2134512
2196716
2476704
2756680
3036668となり、メモリが開放されていないと思われます。
このメモリを開放したいのですが、方法が解りません。
どうしたらよいでしょうか。 -
横からすみません。
私の 環境でも girlie さんの指摘する現象が発生しました。中博俊 さんからの引用 われわれ凡人が考えるよりはよりましな開放を行ってくれるはずです。
どうしても今開放して欲しいという場合にはGC.Collect()で強制的に発動させることが可能です。
一般論ではそうなっているはずですが、
VB.2005 では メモリが開放されず、 同じソースでもVB.2003 ではメモリが開放されていました。
とりあえずの回避策としては1.Event 宣言している クラスは無駄にインスタンス化しない。
2.EventではなくEventHandlerを使ったデリゲートを利用する。などが考えてみてはいかがでしょうか?
-
ちょっと試してみたところ、もう少しループ回数を増やしてみたりすると、たまの消費メモリが減ったりするようです。なので、確かに解放されにくいみたいですが、まったく解放されないわけではないように思います。
どうも、クラス内に Event があるとコンパイラによって
- Private Shared __ENCList As ArrayList というフィールドが追加される
- 静的コンストラクタが追加される (ここで __ENCList = New ArrayList() としている)
- コンストラクタに __ENCList.Add(New WeakReference(Me)) というコードが追加される
といった操作が行われるようです。なんのために WeakReference で参照するようにしているのかはわかりませんが、これがあるために解放されにくくなるのかもしれません。
ちなみに、C# の場合はこういったコードはまったく生成されないようなんですが、この __ENCList ってなんのためにあるんでしょうね。