none
C#のメモリ管理について RRS feed

  • 質問

  • アプリケーション:

     サービス

     

    処理内容:

     EntryWrittenEventHandlerを使ってイベントログを監視するアプリ

     

     無限LoopにSleep(1000)を使ってイベントを待っています。

     

    困っている点:

     EntryWrittenEventHandlerで追加する関数はstaticにしないと追加出来ないので、

     staticにしています。

     この関数が呼ばれるだけでメモリを消費し、この関数を抜けても

     メモリが解放されません。

     

     イベントに登録したstatic関数のメモリ解放方法などがあるのでしょうか。

     

     メモリ系の問題は初めてなので、苦戦しています。

     お手数おかけしますが、どなたかご教授願います。

     

     

     

    2007年8月1日 3:17

すべての返信

  • >EntryWrittenEventHandlerで追加する関数はstaticにしないと追加出来ないので、
    >staticにしています。

     

    static でないといけないという制限はないと思うのですが、本当ですか?


    >この関数が呼ばれるだけでメモリを消費し、この関数を抜けても
    >メモリが解放されません。
    >イベントに登録したstatic関数のメモリ解放方法などがあるのでしょうか。

    メモリが消費されているという根拠はなんでしょうか?


    関数内で生成したオブジェクトはメモリを消費しているでしょうが、関数を抜けたからといってすぐには解放されないのは確かです。スタックに積んだ参照が消えてもです。次回 GC が実行されたときに解放されます。

     

    2007年8月1日 4:15
  • >static でないといけないという制限はないと思うのですが、本当ですか?

    「静的でないフィールド、メソッド、またはプロパティ 'EventWatch.Service1.elog_EntryWritten(object, System.Diagnostics.EntryWrittenEventArgs)' で、オブジェクト参照が必要です。」

    というエラーが出ているのでコールバック関数はstaticにしています。

     

    >メモリが消費されているという根拠はなんでしょうか?

    タスクマネージャでプロセスが使用しているメモリ量を確認しました。

    処理経過後5分経過しても10分経過してもメモリが元に戻らなかったので、

    解放されていないのではないかと思いました。

     

     

    2007年8月2日 2:53
  •  net_test さんからの引用

    >static でないといけないという制限はないと思うのですが、本当ですか?

    「静的でないフィールド、メソッド、またはプロパティ 'EventWatch.Service1.elog_EntryWritten(object, System.Diagnostics.EntryWrittenEventArgs)' で、オブジェクト参照が必要です。」

    というエラーが出ているのでコールバック関数はstaticにしています。


    コンパイラは「コールバック関数を静的にして下さい」とは言っていませんよね。
    static な場所で、static でないもの参照できないだけです。

    Code Snippet

    class A
    {
     static void B()
     {
      C(); // <- これがダメ。
     }

     void C(){}
    }

     

     


     net_test さんからの引用

    >メモリが消費されているという根拠はなんでしょうか?

    タスクマネージャでプロセスが使用しているメモリ量を確認しました。

    処理経過後5分経過しても10分経過してもメモリが元に戻らなかったので、

    解放されていないのではないかと思いました。


    その計測方法はとても杜撰です。タスクマネージャが指しているものは一体何なのかを詳しく知っておいたほうがよいでしょう。
    とりあえず、.NET のガベージコレクタは必要になるまで実行されません。ぶっちゃけて言えば、片付ける必要のないゴミは放置しています。時間経過がトリガになって元に戻るという事はありません。

    2007年8月2日 4:28
  • Task Manager では正確なヒープの正確な情報は得られないので、 パフォーマンスモニタで確認してはいかがでしょうか。

    コマンドプロンプトから perfmon で、開くことが可能です。

     

    計測したいプロセスに対して、".NET CLR Memory" を選んで、"# Bytes in all heaps" などを選べばよいでしょう。

    実際に現象が発生する手順を繰り返し、メモリが右肩上がりであれば、メモリリークの可能性が高いです。

    2007年8月14日 6:31