1

サーバー上で非常に長い間 (数か月) 実行される .NET C# Windows サービスをコーディングしました。

昨日確認したところ、600MBのメモリを使用していることがわかりました。サービスを再起動したところ、現在 60MB の RAM を使用しています。

なぜそんなに多くのメモリを使用しているのかを調べ始めました。 次の関数はメモリ リークを引き起こしますか?

StreamReader の .Close() が欠落していると思います。

テストとして、次の関数をループで 1000 回実行しましたが、メモリが増加することはありませんでした。

private static string GetTemplate(string queryparams)
{
    WebRequest request = HttpWebRequest.Create(uri);
    request.Method = WebRequestMethods.Http.Get;
    WebResponse response = request.GetResponse();
    StreamReader reader = new StreamReader(response.GetResponseStream());
    string tmp = reader.ReadToEnd();
    response.Close();
}
4

6 に答える 6

4

あなたのコードは応答を閉じていますが、リーダーではありません。

var tmp = string.Empty;

using(var reader = new StreamReader(response.GetResponseStream())
{
    tmp = reader.ReadToEnd();  
}

/// do whatever with tmp that you want here...
于 2012-05-10T15:56:58.583 に答える
4

IDisposableなどを実装するすべてのオブジェクトを破棄する必要がWebResponseありStreamReaderます。

private static string GetTemplate(string queryparams)
{
    WebRequest request = HttpWebRequest.Create(uri);
    request.Method = WebRequestMethods.Http.Get;
    using(var response = request.GetResponse())
    using(var reader = new StreamReader(response.GetResponseStream())
       string tmp = reader.ReadToEnd();
}
于 2012-05-10T15:57:36.947 に答える
3

コードはメモリ リークを生成しません。

誰もが指摘するように、コードは理想的ではありません (予想よりも遅くリソースを閉じることになります) が、GC が実行されて未使用のオブジェクトがファイナライズされると解放されます。

本当にメモリリークが発生していますか、それとも半ランダムな値に基づいてメモリリークがあると思い込んでいますか? オブジェクトが割り当てられていない場合でも、CLR はマネージ ヒープによって使用されるメモリを解放しない場合があります。十分なメモリ負荷がない場合 (特に x64 では)、GC を実行する必要がない場合があります。

于 2012-05-10T16:12:27.283 に答える
2

メモリが増加するかどうかを確認したい場合は、1000回をはるかに超える反復をお勧めします。それがあなたのメモリリークである場合、各反復は少量のメモリしか占有しません。

それがメモリリークの原因であるかどうかは.Close()わかりませんが、StreamReaders を使い終わったときの良い習慣です。

于 2012-05-10T16:01:02.423 に答える
1

StreamReaderでは、「using」を使用することをお勧めします。そうすると、オブジェクトがスコープ内になくなったときにIDisposableインターフェイスが実装されます。

using (var reader = new StreamReader(FilePath))
  {
    string tmp = reader.ReadToEnd();
  }

あなたの問題に関しては、1000回はそれほど多くの再帰ではありません。アプリを数時間そのままにして、数十万の時間を計ってみてください。そうすれば、より良い兆候が得られます。

于 2012-05-10T16:03:00.123 に答える
0

潜在的に、それを使用する頻度に依存する可能性があります。これは、Reader の Dispose() への明示的な呼び出しを使用しないためです。これらの行でできることをすべて実行したことを確認するには、次のように書き留めます。

private static string GetTemplate(string queryparams)
{
    WebRequest request = HttpWebRequest.Create(uri);
    request.Method = WebRequestMethods.Http.Get;
    WebResponse response = request.GetResponse();

    using(StreamReader reader = new StreamReader(response.GetResponseStream())){

         string tmp = reader.ReadToEnd();
         response.Close();
    }

    // here will be called Dispose() of the reader 
    // automatically whenever there is an exception or not.
}
于 2012-05-10T15:57:12.937 に答える