我最近遇到错误“ObjectDisposedException:无法访问已关闭的流”
[ObjectDisposedException: Cannot access a closed Stream.]
System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count) +10184402
System.Security.Cryptography.CryptoStream.FlushFinalBlock() +114
System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing) +48
使用格式后的代码:
using (var stream = new MemoryStream())
{
using (var hashStream = new CryptoStream(stream,
new SHA256Managed(), CryptoStreamMode.Write))
using (var writer = new TextWriter(hashStream))
{
writer.Write("something");
}
// ^-- Exception occurs on hashStream Dispose
// While naively I assumed that TextWriter.Dispose wouldn't touch the
// underlying stream(s).
return stream.ToArray();
}
因此,引发异常是因为TextWriter的Dispose释放了包装的Stream(hashStream)。我的问题是:
此约定是否(使用默认构造函数/参数)应用于.NET中的所有流?
是否有佳能讨论此资源使用模式?例如,可以假设CryptoStream会关闭MemoryStream吗?我知道答案,are other questions specifically about this,但如果有这样的话,我希望根据设计指南来解决。
这种行为记录在哪里?
我找不到TextWriter(stream)
或CryptoStream
构造函数中讨论的“所有权” - 当然我只是在查看错误的位置。 (更新:显然我在阅读时失败了,正如其文件80所指出的那样 在TextWriter构造函数文档中记录。)
编写此类代码的通用方法是什么?
也就是说,需要读取底层流(在所有操作结束时,因此仍然打开),而所有嵌套流应该完全关闭/刷新 - 一个简单的{{3例如,还不够。
答案 0 :(得分:5)
the StreamWriter() documentation中特别提到了这一点。
当调用StreamWriter.Dispose时,StreamWriter对象在提供的Stream对象上调用Dispose()。
答案 1 :(得分:3)
在阅读using
语句C# spec并查看一些已实现的流(内存,文件等)后,我发现默认行为是在调用{{{ 1}}。
在某些流中您可以明确声明您不想处理基础流,例如在Dispose()
中:
DeflateStream
leaveOpen类型:System.Boolean如果为true,则保持流对象处于打开状态 在处理DeflateStream对象之后;否则,错误。
当然,您可以通过不使用using语句来处理处理,或者实现一个public DeflateStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen)
类来封装您的流并且不会丢弃底层流。