当我对以下代码块运行代码分析时,我得到以下消息:
对象'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);
}
}
我不明白为什么它可能会被调用两次,以及如何修复它以消除错误。有什么帮助吗?
答案 0 :(得分:19)
我努力解决这个问题,并发现示例here非常有用。我将发布代码以便快速查看:
using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(stream))
{
// Use the writer object...
}
}
使用try / finally替换外部using语句,确保在StreamWriter中使用后将BOTH置为空,并在处理之前检查以确保它在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();
}
这样做可以解决我的错误。
答案 1 :(得分:13)
为了说明,让我们编辑你的代码
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
无论如何,好点,因此编辑:)
答案 2 :(得分:8)
BinaryReader / BinaryWriter会在处理时为您配置基础流。您无需明确地执行此操作。
要修复它,您可以删除Stream本身的使用。
答案 3 :(得分:5)
您的作家将始终处理您的信息流。
答案 4 :(得分:5)
明确要求正确实现Dispose,不要在意它是否在同一个对象上被多次调用。虽然对Dispose的多次调用有时表示逻辑问题或代码可以更好地编写,但我改进原始发布代码的唯一方法是说服Microsoft向BinaryReader和BinaryWriter添加一个选项,指示他们不要处理他们的传递 - 在流中(然后使用该选项)。否则,即使读者或作者抛出其构造函数,确保文件被关闭所需的代码也会非常难看,只是让文件被多次处理似乎更清晰。
答案 5 :(得分:0)
只要您确定相关对象正确处理多个 Dispose
调用并且您的控制流具有无可挑剔的可读性,就禁止 CA2202。 BCL 对象通常正确实现 Dispose
。流因此而闻名。
但是,如果您还没有进行单元测试来探索该场景,则不一定要信任第三方或您自己的流。返回 Stream
的 API 可能返回脆弱的子类。