VB.NET 2008 Eventステートメントのメモリ増加の原因とは?

このQ&Aのポイント
  • VB.NET 2008のEventステートメントを使用した場合、メモリが増加する現象が見受けられます。
  • 同じクラスで他のデータ型を使用した場合にはメモリの増加は見られません。
  • この現象はメモリリークとは言えませんが、なぜメモリが増加するのか疑問です。
回答を見る
  • ベストアンサー

VB.NET 2008 Eventステートメント

VB.NET 2008 以下の実装で実行したところ、GC強制実行後のメモリ状態に疑問を持ち質問しました。 Eventを所持したクラスの生成、削除を繰り返し、GCを強制実行したところ、 16バイトごと増加していきます。 Class1で定義したm_eventをイベントから別のタイプ、例えばIntegerやString型に変更して、 同様に実行したところ、メモリの増加は見受けられません。 なぜでしょうか? またこの現象はメモリリークといえるのでしょうか? Public Class Class1 Public Sub New() End Sub Private Event m_event() End Class Sub Main() GC.Collect() Debug.Print("####") Debug.Print(GC.GetTotalMemory(False)) Dim cls As Class1 For i As Integer = 0 To 1000 cls = New Class1 cls = Nothing If i = 0 Then GC.Collect() Debug.Print(GC.GetTotalMemory(False)) End If Next GC.Collect() Debug.Print(GC.GetTotalMemory(False)) Debug.Print("@@@@") End Sub

質問者が選んだベストアンサー

  • ベストアンサー
  • hogya
  • ベストアンサー率67% (49/73)
回答No.1

クラスに未使用のイベントが多数含まれると、メモリが不必要に消費するということですから、リークとまではいえないのでないでしょうか。(今回の場合は未使用のイベントひとつのクラスが多数でしょうが) ただ、イベントに紐づけたハンドラを解除しないで放っておいたりすると発生するのはリークになるでしょうね。 参考 http://msdn.microsoft.com/ja-jp/library/yt1k2w4e(v=vs.90).aspx

akimtakimt
質問者

補足

回答ありがとうございます。 イベントに関しては、ただ所持しているだけでハンドラ登録は行っていません。 再度本日テストしたところ、デバッグビルド状態だと本現象が発生するようです。 リリースビルドで生成した実行ファイルでは本現象は発生しませんでした。 MSの不具合でしょうか。。。。

関連するQ&A

  • VB.NET スレッドからのイベント受信について

    はじめて質問させていただく、VB.NET初心者です。 ただいまスレッド、イベント処理を作成中で Form1にButton1、Label1を貼り付け以下の様なプログラムを記述しました。 (スレッドにて5秒ごとにイベントを発生させます。) 'イベント引数 Public Class EventArgs Inherits System.EventArgs Public nowTime As String End Class 'イベント発行 Public Class EventTest Public Event _event(ByVal sender As Object, ByVal e As EventArgs) Public Sub Go() Dim args As New EventArgs() args.nowTime = Now.ToString RaiseEvent _event(Me, args) End Sub End Class 'フォーム内処理 'スレッド宣言 Dim MyThread As New System.Threading.Thread(AddressOf _Thread) Private WithEvents _test As New EventTest() 'イベント受信   Private Sub Handler(ByVal sender As System.Object, ByVal e As EventArgs) Handles _test._event Label1.Text = e.nowTime End Sub 'スレッド(5秒間隔でイベント発行) Private Sub _Thread() Dim i As Integer For i = 0 To 99 System.Threading.Thread.Sleep(5000) _test.Go() Next End Sub 'スレッド起動 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click MyThread.Start() End Sub End Class 開発環境から普通に実行すれば正常に動作している様なのですが、 イベント受信部(Handler)のLabel1.Text = e.nowTime部に ブレークポイントを置いてLabel1のウォッチをするとその時点で 処理がとまってしまいます。なぜとまるのかが知りたいです。 作成方法がまずいのでしょうか? 皆様よろしくお願いいたします。

  • 複数フォームへのイベントの通知方法について

    Visual Basic2005にてプログラミングをしております。プログラミング初心者です。 以下、どなたかご教授いただけませんでしょうか? あるクラスを定義し、そのクラスの1つのインスタントがイベントを出した時に、 フォーム1~フォーム3の各Formにイベントを通知する様なプログラムを作成しております。 複数フォームへのイベントの通知方法として、以下の様なやり方は一般的に正しいのでしょうか? プログラムを実行させて見ると、動作上は何の問題もなく動いている様に見えますが、 プログラミング経験が少ない事もあり、以下のやり方が本当に正しいのかどうか、あまり自信が持てません。 どなたかご教授いただけると助かります。宜しくお願い致します。 =================================================================================== 'クラスA Public Class classA   Public Event StatusChange(ByVal status As Integer)   Public Event MassageOutput(ByVal message As String)   Private status As Integer   Private Sub EventReport1()       status = 5       'statusの変更を通知するイベントを生成させる       RaiseEvent StatusChange(status)   End Sub   Private Sub EventReport2()       'メッセージを通知するイベントを生成させる       RaiseEvent MassageOutput("メッセージを通知します")   End Sub End Class 'モジュール Module moduleA   Public myInstance As New classA End Module 'フォーム1 Public Class form1   Private WithEvents myInstance1 As classA   Public Sub New()       InitializeComponent()       myInstance1 = myInstance   End Sub   Private Sub StatusChange(ByVal message As String) _                Handles myInstance1.MassageOutput       TextBox1.Text = message   End Sub End Class 'フォーム2 Public Class form2   Private WithEvents myInstance1 As classA   Public Sub New()       InitializeComponent()       myInstance1 = myInstance   End Sub   Private Sub StatusChange(ByVal status As Byte) _                Handles myInstance1.MassageOutput       TextBox1.Text = status.ToString   End Sub End Class 'フォーム3 Public Class form3   Private WithEvents myInstance1 As classA   Public Sub New()       InitializeComponent()       myInstance1 = myInstance   End Sub   Private Sub StatusChange(ByVal status As Byte) _                Handles myInstance1.MassageOutput       TextBox1.Text = (status + 10).ToString   End Sub End Class ===================================================================================

  • vb コンボボックスのイベントについて

    こんばんわ。 コンボボックスで、 指定の値をマウス操作でクリックしたときと、 キーボードの上下で、移動後returnを押したときだけ、 MsgBox "処理実行" を実行したいです。 keystateを使ってみたのですが、前の情報が残っているのかうまくいきません。keystateの情報をクリアさせるか、シンプルに上記を動作させる何かよい方法はありますでしょうか。 Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Dim flg1 As Boolean Private Sub form_load() Combo1.AddItem (11) Combo1.AddItem (22) Combo1.AddItem (33) Combo1.AddItem (44) End Sub Private Sub Combo1_Keyup(KeyCode As Integer, Shift As Integer) If KeyCode = 13 Then 'return flg1 = True Call Combo1_click End If End Sub Private Sub Combo1_click() If (GetKeyState(&H26) <> 0) Or (GetKeyState(&H28) <> 0) Then ' ↑↓ If flg1 = False Then Exit Sub End If End If MsgBox "処理実行" flg1 = False End Sub

  • VB2008: 独自例外とは?

    独自例外の確認ための質問をします。 独自例外の発生をキャッチして表示する術がわからなくて苦肉の策でエラートラップを利用。 しかし、こういう事であれば何も独自例外を設定する必要がありません。 と思ったり、「スルーだからテストに<0除算>を選んだのが悪いのか?」と考えたり。 ともかく、判っているのか判っていないのかが判らない状態に陥っています。 そういうことで、独自例外について少し教えて頂ければ幸いです。 ' ============================== ' クラスプログラミング; 演習2 ' ============================== Module theClass   Sub Main()     On Error GoTo Error_Main     Dim T1 As New TEST1     Debug.Print(T1.MembersLengthAverage.ToString) Exit_Main:     Exit Sub Error_Main:     ErrorMsg(Err.Description & "(Main)")     Resume Exit_Main   End Sub End Module ' ================================================================== ' クラス TEST1 ' ================================================================== <Serializable()> Public Class TEST1   Private _MemberCount As Integer   Private _Member1 As String   Private _Member2 As String    ReadOnly Property MembersLengthAverage() As Integer     Get       If _MemberCount <> 0 Then         Return (_Member1.Length + _Member2.Length) \ _MemberCount       Else         Throw New System.Exception("TEST1: 除算エラーが発生しました。" )       End If     End Get   End Property   Public Sub New()     _Member1 = ""     _Member2 = ""   End Sub End Class

  • コールバックでイベントを使うメリットは何でしょうか

    コールバック関数を実行するのに、わざわざイベントを使う利点は何でしょうか。 下記のコードでは、どちらでも大して変わらないように見えますが・・・ Module modMain Sub Main() Dim myRaise As clsMyRaiseEvent = New clsMyRaiseEvent 'イベントを使った使用法 AddHandler myRaise.MyEvent, New clsMyRaiseEvent.dlgMyEvent(AddressOf MyCallBack) myRaise.Test1() '関数ポインタ的な使用法 myRaise.callback = New clsMyRaiseEvent.dlgMyEvent(AddressOf MyCallBack) myRaise.Test2() Console.ReadLine() End Sub 'コールバック関数 Private Sub MyCallBack(ByVal aEx As Exception) Console.WriteLine("Called") End Sub End Module Public Class clsMyRaiseEvent Public Delegate Sub dlgMyEvent(ByVal aEx As Exception) Public Event MyEvent As dlgMyEvent 'デリゲート型のイベント Public callback As dlgMyEvent Public Sub Test1() RaiseEvent MyEvent(New Exception) End Sub Public Sub Test2() callback(New Exception) End Sub End Class

  • VB6.0 KeyDownイベントの対応

    VB6.0を使ってプログラム中ですが、下記の  Command10_KeyDown で、複合キー「 Ctrl + ↓」 だとイベント KeyDown を受信できるのですが、単純な キー「↓」だと、イベント KeyDown を受信でず、他のボタンにフォーカスが移ってしまいます。 Comman10_GotFocus に何か対応策を入れて、単純な キー「↓」のイベント KeyDown を受信する方法はないでしょうか? Private Sub Command10_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = 40 Then execsub001() End If End Sub Private Sub Commnad10_Click() execsub001() End Sub Private Sub Comman10_GotFocus() 上記問題への対応策を此処に記述したい End If Private Sub execsub110() 内容は省略 End Sub

  • VB6構造体をVB2008クラスで行う場合

    何方かの質問「VB6構造体をVB2008クラスで行う場合」 の回答プログラムにて参考とさせて頂きましたが 申し訳ありません、初心者しにて・・・・・教えてください。 値を「登録、参照部分」のクラス(抜粋) Public Class Program   Public Shared Sub Main()    (省略)   End Sub End Class 上記部分なのですが (1)Sharedを使用する訳はなんでしょうか?(省いても問題ありませんか?) (2)登録、参照部分のクラスPublic Shared Sub Main()を「登録のメソッド」と「参照のメソッド」に   分けたいのですがどうしてもうまくいきません。   何方か御教授願えないでしょうか? よろしくお願いします。 「以下何方かの質問の回答プログラム」 ■クラス+コレクションクラス Public Class Group   Public MainID As Integer   Public SubID As Integer   Public Value1 As Integer   Public Value2 As Integer End Class Public Class GroupCollection : Inherits System.Collections.Generic.Dictionary(Of Integer, Group)   Public Shadows Sub Add(ByVal Item As Group)     MyBase.Add(Item.SubID, Item)   End Sub End Class Public Class Program   Public Shared Sub Main()     Dim DataDict As New GroupCollection     Dim NewGroup As New Group     NewGroup.MainID = 1     NewGroup.SubID = 101     NewGroup.Value1 = 123     NewGroup.Value2 = 234     DataDict.Add(NewGroup)     Console.WriteLine(DataDict.Item(101).Value2) ' 出力 234   End Sub End Class

  • Rubyのクラス

    class Test def initialize @ary = Array.new(size){false} end def print _print end def _print print"#{@ary}" end end test = Test.new(5) test.print 上記のプログラムはエラーが出て実行できません。期待している動作は[false,false,false,false,false]です。どうしてエラーが出るか教えていただきたいです。また、解決策もよろしくお願いします。

    • ベストアンサー
    • Ruby
  • VB.NETでDLL関数を呼び出すには

    VB.NETでDLLの関数を呼び出す時に、 NewではなくCreateObject()を使って呼び出すには、 どのように記述をすればよいのでしょうか。 具体的には、 ソリューション名 ClassLibrary1で ---------------------------------- Imports System.Windows.Forms Public Class Class1 Public Sub test() MessageBox.Show("テスト") End Sub End Class ---------------------------------- のコードをビルドしてClassLibrary1.dllを生成して、 ソリューション名 ConsoleApp1で ---------------------------------- Imports ClassLibrary1 Module Module1 Sub Main() Dim obj As Class1 obj = New Class1() 'obj = CreateObject("Class1") obj.test() End Sub End Module ---------------------------------- のコードをビルドして実行すると、 正しく実行できますが、 obj = New Class1() を obj = CreateObject("Class1") のようにすると図のようなエラーになります。 Newではなく、CreateObject()を使ってDLLを呼び出すには、 どのように記述をすればよいのでしょうか。 よろしくお願いします。 (Windows10)(Visual Studio 2022)

  • 「Debug.Print i = i + 1」がFalseになる。

    Sub test() Dim i As Long i = 0 Debug.Print i = i + 1 End Sub を実行すると False がイミディエイトウインドウに表示されます。 理由が知りたいです。 よろしくお願いします。

専門家に質問してみよう