C#StreamReader关闭-内存泄漏?

C#StreamReader关闭-内存泄漏?,c#,.net,visual-studio,.net-4.0,C#,.net,Visual Studio,.net 4.0,我编写了一个.NETC#windows服务,它在我们的服务器上运行了很长一段时间(几个月) 昨天我检查了一下,发现它使用了600MB的内存。 我重新启动了服务,现在它使用了60MB的ram 我已经开始检查它为什么会占用这么多内存。 以下功能是否会导致内存泄漏? 我认为StreamReader缺少.Close()。 作为测试,我已经在循环中运行了1000次以下函数,但没有看到内存增加 private static string GetTemplate(string queryparams) {

我编写了一个.NETC#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();
}

您的代码正在关闭响应,但没有关闭读取器

var tmp = string.Empty;

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

/// do whatever with tmp that you want here...

您的代码正在关闭响应,但没有关闭读取器

var tmp = string.Empty;

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

/// do whatever with tmp that you want here...

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

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.
}

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

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.
}

所有实现了
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();
}

所有实现了
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();
}

如果你想知道内存是否会增加,我建议你进行1000次以上的迭代。如果是内存泄漏,每次迭代只会占用一小部分内存


我不确定这是否是内存泄漏的原因,但最好在使用完StreamReader后关闭它。

如果您想知道内存是否会增加,我建议使用1000多次迭代。如果是内存泄漏,每次迭代只会占用一小部分内存


我不确定这是否是内存泄漏的原因,但最好在使用完StreamReader后关闭它。

使用StreamReader时,最好使用“using”,然后在对象不再在作用域中时实现IDisposable接口

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

至于你的问题,1000次并不是很多次的递归。试着离开应用程序几个小时,然后打上几十万个时钟,这会给你一个更好的指示。

对于StreamReader,最好使用“使用”,然后在对象不再在范围内时实现IDisposable接口

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

至于你的问题,1000次并不是很多次的递归。试着让应用程序运行几个小时,然后计时10万次,这会给你一个更好的指示。

代码不会产生内存泄漏

正如大家所指出的那样,代码并不理想(这将导致关闭资源的时间比您预期的要晚),但当GC开始运行并最终确定未使用的对象时,它们将被释放


你确定你看到了内存泄漏,还是仅仅假设你有一个基于半随机值的内存泄漏?即使未分配任何对象,CLR也可能无法释放托管堆使用的内存。如果没有足够的内存压力(特别是在x64中),GC可能不需要运行。

代码不会产生内存泄漏

正如大家所指出的那样,代码并不理想(这将导致关闭资源的时间比您预期的要晚),但当GC开始运行并最终确定未使用的对象时,它们将被释放


你确定你看到了内存泄漏,还是仅仅假设你有一个基于半随机值的内存泄漏?即使未分配任何对象,CLR也可能无法释放托管堆使用的内存,如果没有足够的内存压力(特别是在x64中),GC可能不需要运行。

ResponseStream和Response如何?两者都实现IDisposable,并且应该被释放。因此,您的代码缺少2条使用语句的语句。我理解我缺少对读卡器的关闭:)。最大的问题是,这会导致600mb ram的使用吗?ResponseStream和Response如何?两者都实现IDisposable,并且应该被释放。因此,您的代码缺少2条使用语句的语句。我理解我缺少对读卡器的关闭:)。最大的问题是,这会导致600mb ram的使用吗?流还实现IDisposable。@处理
StreamReader
的spender将关闭(并处理)底层流。同意。但是,通常我也会将其包括在内,以防我以后决定转移到另一个处理不是隐式的读取实现。Stream还实现IDisposable。@spender处理
StreamReader
将关闭(并处理)基础流。同意。但是,通常我也会将其包括在内,以防我以后决定转移到另一个不隐含处理的读取实现。对于内存泄漏一点也不确定,我只是在任务管理器中看到了使用600mb ram(我总共只有4gb)的服务,这对我来说真的没有意义。请修复您的代码:)。要确认是否是泄漏,最好使用.Net内存探查器(搜索-大量信息),但您可以通过添加对GC的调用进行欺骗。收集足够多的数据以进行调查,并查看内存使用是否一直在增长或只是稳定在某个值。请确保您知道如何重现该条件,否则您将如何知道行为是否发生了变化。Alexei,StreamReader等是否有一些特殊之处,可以在未经处理的情况下不会导致内存泄漏?如果应用程序退出,当然,整个过程将与分配的任何资源一起终止。但是,在一个长时间运行的服务中,这可能是一个真正的问题。我遗漏了什么吗?如果没有处理,没有CLR对象泄漏内存(错误不算在内)。所有管理本机资源(如FileStream)的CLR类都具有Dispose和Finalizer,因此,如果您未能处理对象,它最终将被垃圾收集并释放非管理资源。对于纯托管对象(如大多数xxreader类),有