繁体   English   中英

“对象可以被多次处理”错误

[英]“Object can be disposed of more than once” error

当我对以下代码块运行代码分析时,我收到此消息:

对象 'stream' 可以在方法 'upload.Page_Load(object, EventArgs)' 中多次处理。 为避免生成 System.ObjectDisposedException,您不应在一个对象上多次调用 Dispose。

using(var stream = File.Open(newFilename, FileMode.CreateNew))
using(var reader = new BinaryReader(file.InputStream))
using(var writer = new BinaryWriter(stream))
{
    var chunk = new byte[ChunkSize];
    Int32 count;
    while((count = reader.Read(chunk, 0, ChunkSize)) > 0)
    {
        writer.Write(chunk, 0, count);
    }
}

我不明白为什么它可能会被调用两次,以及如何修复它以消除错误。 有什么帮助吗?

我在这个问题上苦苦挣扎,发现这里的例子非常有帮助。 我将发布代码以便快速查看:

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

用 try/finally 替换外部 using 语句,确保在 StreamWriter 中使用流后将其设为空,并在处理之前检查以确保它在 finally 中不为空。

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

这样做清除了我的错误。

为了说明,让我们编辑您的代码

using(var stream = File.Open(newFilename, FileMode.CreateNew))
{
    using(var reader = new BinaryReader(file.InputStream))
    {
        using(var writer = new BinaryWriter(stream))
        {
            var chunk = new byte[ChunkSize];
            Int32 count;
            while((count = reader.Read(chunk, 0, ChunkSize)) > 0)
            {
                writer.Write(chunk, 0, count);
            }
        } // here we dispose of writer, which disposes of stream
    } // here we dispose of reader
} // here we dispose a stream, which was already disposed of by writer

为避免这种情况,只需直接创建编写器

using(var reader = new BinaryReader(file.InputStream))
    {
        using(var writer = new BinaryWriter( File.Open(newFilename, FileMode.CreateNew)))
        {
            var chunk = new byte[ChunkSize];
            Int32 count;
            while((count = reader.Read(chunk, 0, ChunkSize)) > 0)
            {
                writer.Write(chunk, 0, count);
            }
        } // here we dispose of writer, which disposes of its inner stream
    } // here we dispose of reader

edit :考虑到 Eric Lippert 所说的内容,如果 BinaryWriter 抛出异常,则确实可能有一段时间仅由终结器释放流。 根据 BinaryWriter 代码,这可能发生在三种情况下

  If (output Is Nothing) Then
        Throw New ArgumentNullException("output")
    End If
    If (encoding Is Nothing) Then
        Throw New ArgumentNullException("encoding")
    End If
    If Not output.CanWrite Then
        Throw New ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable"))
    End If
  • 如果您没有指定输出,即如果流为空。 这应该不是问题,因为空流意味着没有要处理的资源:)
  • 如果您没有指定编码。 由于我们没有使用指定编码的构造函数形式,所以这里也应该没有问题(我没有过多研究编码构造函数,但可能会抛出无效的代码页)
    • 如果您不传递可写流。 这应该在开发过程中很快被发现......

无论如何,好点,因此编辑:)

BinaryReader/BinaryWriter 会在处理时为您处理底层流。 您不需要明确地这样做。

要修复它,您可以删除 Stream 本身周围的 using。

您的作者将始终处理您的流。

明确要求 Dispose 的正确实现不关心它是否在同一个对象上被多次调用。 虽然对 Dispose 的多次调用有时表明存在逻辑问题或可以更好地编写代码,但我改进原始发布代码的唯一方法是说服 Microsoft 向 BinaryReader 和 BinaryWriter 添加一个选项,指示他们不要处理传递的 -在流中(然后使用该选项)。 否则,即使读取器或写入器抛出其构造函数,确保文件关闭所需的代码也会非常丑陋,以至于简单地多次处理文件看起来会更干净。

每当您确定相关对象正确处理多个Dispose调用并且您的控制流具有无可挑剔的可读性时,就禁止 CA2202。 BCL 对象通常正确实现Dispose 流因此而闻名。

但是,如果您还没有进行单元测试来探索该场景,则不一定要信任第三方或您自己的流。 返回Stream的 API 可能返回脆弱的子类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM