1

我编写了一个在我们的服务器上运行很长时间(几个月)的 .NET C# windows 服务。

昨天我查了一下,发现它使用了 600MB 的内存。我重新启动了服务,现在它使用 60MB 内存。

我已经开始检查为什么它使用这么多内存。 下面的函数会导致内存泄漏吗?

我认为它缺少 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的对象WebResponseStreamReader应该被处理掉。

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,最好使用“使用”,然后当对象不再在范围内时实现 IDisposable 接口。

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

至于你的问题1000次不是很多递归。尝试离开应用程序几个小时并计时几十万,这将为您提供更好的指示。

于 2012-05-10T16:03:00.123 回答
0

它可能取决于您使用它的频率,因为您不使用对 Reader 的 Dispose() 的 esplicit 调用。为确保您在这些行中尽了最大努力,请将它们写下来,如下所示:

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 回答