了解流和它们的生命周期(刷新、处理和关闭)

29
注意:我已经阅读了以下两个问题:Can you explain the concept of streams?C# using streams。我正在使用C#进行编码。
1. 在几乎所有使用流的代码示例中,都会调用.Dispose()、.Flush()、.Close()这三个函数。 a. 对于流的概念,这些函数能达到什么目的? b. 如果我没有对存储在变量中的流进行处理,那么我的应用程序是否存在泄漏? c. 为什么需要调用这些函数?我看过一些不这样做也能完成任务的代码示例(没有明显的错误)。
2. 我当前正在构建一个类,其中包含一个主要方法(我们称之为GetStream()),通过myWebRequest.GetResponse().GetResponseStream()返回一个流。 主要方法GetStream()返回一个Stream对象,可用于需要流的任何操作(StreamReader、Bitmap()等)。 3. 是否有一种方式可以自动处理最后一次使用后的流(垃圾收集),而无需强制调用.GetStream()的任何人手动处理它?
正如你可能已经注意到的,我的问题比较笼统和一般化。我对流的理解还不够扎实,因此感谢提供任何有关流的深入文章的链接。
1个回答

40

关闭一个流会释放资源(比如文件句柄),而且可能不会做其他什么。清空一个流则是将未写入的数据立即写出;有些流会使用内部缓存以避免向相对昂贵的资源(如磁盘文件或网络管道)进行大量小更新。

在大多数情况下,你需要调用流的CloseDispose方法,否则你的代码就是错误的,因为底层资源不能被释放以供他人使用,直到垃圾回收器到来(谁知道那得多久)。通常情况下,应当优先使用Dispose方法,C#中期望你将所有可释放的对象进行处理。在大多数场景下,你不需要显式地调用Flush方法。

在C#中,惯用的做法是使用using块来调用Dispose方法,这是一种语法糖,实际上是try-finally块,在finally中进行释放,例如:

using (FileStream stream = new FileStream(path))
{
    // ...
}

与功能上相同

FileStream stream;

try
{
    stream = new FileStream(path);
    // ...
}
finally
{
    if (stream != null)
        stream.Dispose();
}

2
最终应该是:if (stream is IDisposable) ((IDisposable) stream).Dispose (); - Gonzalo
11
对于一个不确定是否为IDisposable的变量使用'using'会导致编译错误。然而,技术上应该这样写:如果(stream!= null)stream.Dispose(); - Tim Robinson
在许多情况下,即使调用Dispose,显式关闭流也是一个好主意。关闭流可能需要执行不能保证成功的操作;当出现这些问题时,Close的实现通常会抛出异常,而一些Dispose实现可能会压制这样的异常(吞噬这样的异常是邪恶的,但允许它们从Dispose传播出去通常会破坏先前的异常,这也是邪恶的;实现因考虑哪种邪恶更小而不同)。 - supercat
一个 using 块直接利用 IDisposable 接口,在作用域退出时调用 Dispose() 方法:https://msdn.microsoft.com/zh-cn/library/system.idisposable(v=vs.110).aspx - Dagrooms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接