【问题标题】:Benefit Of Closing Stream关闭流的好处
【发布时间】:2014-03-29 04:23:10
【问题描述】:

从用户的角度来看,关闭流有什么好处?

运行此代码时,无论您是否注释掉response.Close();,它都不会对用户产生明显的影响。

谁能给我一个例子,不关闭流/文件句柄等会给用户带来明显的问题?

    WebRequest request = WebRequest.Create("http://www.microsoft.com");
    WebResponse response = request.GetResponse();
    StreamReader responseStream = new StreamReader(response.GetResponseStream());
    string responseText = responseStream.ReadToEnd();
    Console.WriteLine(responseText); // Displays the HTML of the website
    response.Close();

编辑: 每个人都在说“最好释放/关闭流,以便释放非托管资源”。但是谁能给我一个例子来说明这如何给最终用户带来显着的差异?

【问题讨论】:

  • 假设您的系统中有一个数据库连接。假设许多用户正在使用该系统创建大量连接。如果您没有关闭连接(它们是非托管资源),您可能会遇到连接过多并且新连接将被拒绝的情况
  • 给定的答案有什么遗漏吗?如果是这样,你错过了什么?
  • 我没有机会阅读答案,当我阅读时,我会选择一个作为最佳答案。
  • @Backwards_Dave Ah oke:)

标签: c# stream


【解决方案1】:

通过关闭流,您可以释放与其绑定的资源,尽管这些资源可能会因您使用的流类型而异,其中一些资源的影响比其他资源更大。

FileStream 为例。当流打开时,它在文件上有一个打开的句柄。如果您不关闭它,则在对象在将来某个未指定的时间点被垃圾收集之前,句柄不会被释放。

现在,根据您打开该文件的方式,您可能会遇到问题,例如:

FileStream file = new FileStream("example.dat",FileMode.Open,FileAccess.Read,FileShare.None);

这会获得一个不会被释放的文件的排他锁。这意味着任何其他打开文件和读取的调用都将失败。

所以它总是更好,尤其是在处理与非托管资源接口的类时,一旦完成就释放。

最简单的方法之一是使用using 构造,例如:

using (FileStream file = new FileStream("example.dat",FileMode.Open,FileAccess.Read,FileShare.None)) {
    // Do something useful
}

您可以将using 与实现IDisposable 的任何类一起使用,它会确保一旦超出语句Dispose 的范围就会被调用并释放任何资源。

【讨论】:

    【解决方案2】:

    使用完所有流后,关闭/处置所有流非常重要。
    最好的方法是使用using statement:

    using(StreamReader responseStream = new StreamReader(response.GetResponseStream())
    {
        //streamreader will be disposed automatically,
        //when done executing within brackets.
    }
    

    如果流未/未正确关闭/处置,则会导致内存泄漏。 流使用的资源,将在关闭/释放流时释放。

    每个人都在说“最好处理/关闭流,这样 你释放非托管资源”。但是任何人都可以为我提供一个 展示这如何在最后产生明显差异的示例 用户?

    在您的应用程序中尝试以下代码:

    private void LoopUndisposedStream()
    {
        for(int i = 0; i < 5000000; i++)
        {
           CreateUndisposedStream();
        }
    }
    
    private void CreateUndisposedStream()
    {
        WebRequest request = WebRequest.Create("http://www.microsoft.com");
        WebResponse response = request.GetResponse();
        StreamReader responseStream = new StreamReader(response.GetResponseStream());
        string responseText = responseStream.ReadToEnd();
        Console.WriteLine(responseText); // Displays the HTML of the website
    }
    

    上面的代码是什么,你绝对不应该这样做。但是,由于您要举一个例子,在不处理每个流时显示性能问题。在这里。

    【讨论】:

    • 终结器呢? (这不是不Dispose()它的理由)
    • @C.Evenhuis 抱歉,我不明白你的问题。为什么我们不应该丢弃所有一次性物品?
    • 内存泄漏有什么不好?
    • 您的应用程序将运行得更慢,因为内存被一个未关闭且不再使用的流占用。因此,例如,当您的代码运行 20 次时,您将有 20 个未关闭的流,这将在运行应用程序的 pc 上保留内存。简短的回答:您的应用程序每次打开流而不关闭时都会消耗越来越多的内存。用户用于其他应用程序的内存将越来越少。
    • @MaxMommersteeg 是的,您应该处置任何IDisposable,但终结器应该确保一旦不再引用对象,它的资源被释放。只有在终结器没有正确清理时才会发生真正的内存泄漏。
    【解决方案3】:

    通过关闭Stream 可以释放资源,此外还可以使一些不再需要的对象符合 GargabeCollector 的条件,从而减少内存使用等。

    【讨论】:

      猜你喜欢
      • 2012-07-10
      • 2012-06-20
      • 2014-07-29
      • 2012-08-13
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 2014-06-22
      • 1970-01-01
      相关资源
      最近更新 更多