質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.36%

  • VB.NET

    960questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

【VB.NET】Labelコントロールのテキスト変更によるメモリリークについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 399

garakutayama

score 2

 前提・実現したいこと

VB.NETにてUIソフトを作製しておりますが、メモリリークが発生してソフトが終了してしまいました。
その解決に向けて調査している中で、私には理解できない現象が発生したので教えて頂ければ幸いです。

 現象

メモリリークの原因を調べる中で、Labelコントロールに時刻表示(毎秒更新)する機能の有り無しでタスクマネージャの
メモリ使用量が大きく変わることが分かりました。(モジュール①は毎秒更新、モジュール②は更新なしです)

しかし両モジュール共にGC.Collect()した後に、GC.GetTotalMemory(True)で使用量を確認すると、増加しませんでした。

各モジュールを比べると以下のような状態です。

モジュール タスクスケジューラ GC.GetTotalMemory(True)
①(始め)  30.7 MB 5365.9296875 KB
①(1H後) 114.6 MB 5367.890625  KB
②(始め)  24.5 MB 5379.09375   KB
②(1H後)  24.7 MB 5383.109375  KB

モジュール①: 時刻ラベルを毎秒更新

  Public Sub EverySecProcess()
    lbl_DateTime.Text = Date.Now.ToString("MM/dd HH:mm:ss")                                         '日時ラベルの表示
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    SaveMemoryLog(MethodBase.GetCurrentMethod.Name & ".SetText---End")                               'メモリ量ロギング
  End Sub

モジュール②: 時刻ラベルを更新しない

  Public Sub EverySecProcess()
    'lbl_DateTime.Text = Date.Now.ToString("MM/dd HH:mm:ss")                                         '日時ラベルの表示
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    SaveMemoryLog(MethodBase.GetCurrentMethod.Name & ".SetText---End")                               'メモリ量ロギング
  End Sub

(参考メモリ量ロギング) 

  Public Sub SaveMemoryLog(ByVal MethodName As String)
    Dim fs As System.IO.FileStream = Nothing

    Try
      fs = New System.IO.FileStream(MyPath.MemoryLog, IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.ReadWrite)

      Using sw As New System.IO.StreamWriter(fs, enc)
        Using tw As System.IO.TextWriter = System.IO.TextWriter.Synchronized(sw)
          Dim MsgBuf As String = Date.Now.ToString("yyyy/MM/dd HH:mm:ss:fff") & vbTab
          MsgBuf &= "Total Memory = " & (GC.GetTotalMemory(True) / 1024).ToString.PadRight(12, " ") & " KB" & vbTab
          MsgBuf &= MethodName

          tw.WriteLine(MsgBuf)
          tw.Close()
        End Using
        sw.Close()
      End Using
    Catch ex As Exception
      'ここでは何もしない
    Finally
      'fsがusingでは無く、finallyでcloseしているのは、swのDispose時にすでにcloseされている可能性が有るため
      If fs IsNot Nothing Then
        fs.Close()
        fs.Dispose()
        fs = Nothing
      End If
    End Try
  End Sub

 質問内容  

  • ①変更点は時刻の毎秒更新のみ(changeイベントなども組んでいない)なのですが、これがメモリリークの原因になりうるのでしょうか

  • ②もし①が起こりうるのであれば、メモリリークでソフトが落ちないようにするにはどうすれば良いのでしょうか。

 補足情報(FW/ツールのバージョンなど)

  • 動作環境  
    OS: Windows 10 IoT 2016LTSB (UWF ON)

  • 開発環境
    開発ツール: Visual Studio 2012
    言語: VB.NET
    対象のフレームワーク: .Net Flamework 4.5

 追記① EverySecProcessの呼出元について

スタートアップフォームに作成したtmr_OneSecのTickイベントにて呼んでいます。

  Private Sub tmr_OneSec_Tick(sender As Object, e As EventArgs) Handles tmr_OneSec.Tick
    If MyStatus.IsInitialization Then '初期設定中はタイマー処理は実施しない
      Exit Sub
    End If

    EverySecProcess()                                                                               '毎秒処理の実行

    If OneMinuteCount >= 59 Then                                                                    '毎分処理の実行
      OneMinuteCount = 0
      EveryMinProcess()
    Else
      OneMinuteCount += 1
    End If
  End Sub

 追記② ウィンドウメッセージの処理

大変申し訳ありません。
改めて見直したところ対象フォームのウィンドウメッセージをオーバーライドしていることが分かりました。
(デバイスの利用の為に作成したが消し忘れていたようです)

この関数をコメントアウトしたところ少し見た限りではモジュール①の状態でもリークしないようになりました。
しばらく様子を見たいと思います。

画面更新等の処理はないとの間違った情報を提示してしまい申し訳ありませんでした。

また新たな疑問として下記の処理でリークする理由(なぜLabelのtextchangeでリークするのか)についても、詳しく調べていきたいと思います。

  Protected Overrides Sub WndProc(ByRef m As Message)
    SPREAD.SuspendLayout()'別のスプレッドシートの描画停止処理
    Try
      Select Case m.Msg
        ''Case WINDOW_MESSAGE._DIOEVENT
        ''SignalInput(Integer.Parse(m.WParam.ToString))                                             '監視対象の機器&立ち上がり信号の場合、信号受信処理実行
        Case Else
          MyBase.WndProc(m)                                                                         '<フォームの標準処理の実行>
      End Select
    Catch ex As Exception
      SaveErrorLog(MethodBase.GetCurrentMethod.Name, ex, "m:" & m.Msg)
    End Try
    SPREAD.ResumeLayout()
  End Sub
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • YAmaGNZ

    2018/05/15 23:10

    ラベルのテキストの更新をすることで動作する処理(フォームの再描画等)はありますか?

    キャンセル

  • garakutayama

    2018/05/16 09:53

    返信ありがとうございます。テキスト更新にて動作するイベントとしてはLabelコントロールのTextChangedイベントおよび、その他のtext変更イベントでの描画更新は有りません。

    キャンセル

  • garakutayama

    2018/05/16 11:45

    @sh_akira様、@YAmaGNZ様 大変申し訳ありませんでした。改めて確認したところウィンドウメッセージをオーバーライドしており、その処理をコメントアウトするとモージュール①でもリークしないことが分かりました。描画更新処理はないと書いてしまいましたが訂正するとともに、お詫び申し上げます

    キャンセル

回答 1

check解決した方法

0

皆様ご確認ありがとうございました。

結論としてウィンドウメッセージをオーバーライドしており、その処理をコメントアウトするとモージュール①でもリークしないことが分かりました。

確認不足でお騒がせし申し訳ありませんでした。

なぜリークするのかはまだ調査中ですが、いったん本質問はクローズとさせていただきたいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • VB.NET

    960questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。