9

我最近遇到了一个错误“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)进行了Dispose。我的问题是:

  1. 此约定是否适用于 .NET中的所有流(使用默认构造函数/参数) ?

    是否有佳能讨论这种资源使用模式?例如,是否可以假设 CryptoStream 会关闭 MemoryStream?我知道答案,并且还有其他专门针对此的问题,但如果有的话,我希望根据设计指南来解决。

  2. 这种行为记录在哪里?

    我找不到在TextWriter(stream)orCryptoStream构造函数中讨论的“所有权”——当然我只是在看错误的位置。(更新:显然我阅读失败,正如 itsme86所指出的,这记录在 TextWriter 构造函数文档中。)

  3. 编写此类代码的普遍接受的方法是什么?

    也就是说,需要读取底层流(在所有操作结束时,因此仍然打开),而所有嵌套流应该完全关闭/刷新-例如,简单的CryptoStream.Flush是不够的。

4

2 回答 2

5

StreamWriter() 文档中特别提到了这一点。

调用 StreamWriter.Dispose 时,StreamWriter 对象在提供的 Stream 对象上调用 Dispose()。

于 2014-04-18T22:13:23.297 回答
3

在阅读usingC # 规范并查看一些已实现的流(内存、文件等)后,我发现默认行为是在调用Dispose(). 在某些流中,您可以明确声明您不想处理底层流,例如DeflateStream

public DeflateStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen)

leaveOpen 类型:System.Boolean true 以在处理 DeflateStream 对象后保持流对象打开;否则为假。

当然,您可以通过不使用 using 语句来解决处置问题,或者可能实现一个WrapperStream包装您的流并且不处置基础流的类。

于 2014-04-18T22:56:32.500 回答