c# - pattern - "El objeto se puede eliminar más de una vez" error
recursos no administrados c# (5)
El BinaryReader / BinaryWriter eliminará la transmisión subyacente cuando esté disponible. No es necesario que lo hagas explícitamente.
Para solucionarlo, puede eliminar el uso de todo el Stream.
Cuando ejecuto el análisis de código en el siguiente fragmento de código obtengo este mensaje:
La ''corriente'' del objeto se puede eliminar más de una vez en el método ''upload.Page_Load (object, EventArgs)''. Para evitar generar una excepción System.ObjectDisposedException, no debe llamar a Dispose más de una vez en un objeto.
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);
}
}
No entiendo por qué podría llamarse dos veces, y cómo solucionarlo para eliminar el error. ¿Alguna ayuda?
Luché con este problema y encontré el ejemplo here para ser muy útil. Publicaré el código para una vista rápida:
using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(stream))
{
// Use the writer object...
}
}
Reemplace la declaración de uso externa con una prueba / finalmente asegurándose de AMBOS anular la secuencia después de usarlo en StreamWriter Y verificar para asegurarse de que no es nulo en el finalmente antes de la eliminación.
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();
}
Al hacerlo, aclaró mis errores.
Para ilustrar, editemos su código
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
Para evitar esto, simplemente crea el escritor directamente
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
: para tener en cuenta lo que dice Eric Lippert, podría haber un momento en que la secuencia solo sea lanzada por el finalizador si BinaryWriter arroja una excepción. De acuerdo con el código BinaryWriter, eso podría ocurrir en tres casos
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
- si no especificó una salida, es decir, si stream es nulo. Eso no debería ser un problema ya que una secuencia nula significa que no hay recursos para disponer de :)
- si no especificaste una codificación ya que no usamos el formulario de constructor donde se especifica la codificación, tampoco debería haber ningún problema aquí (no miré demasiado el contructor de codificación, pero puede arrojarse una página de códigos no válida)
- si no pasa una secuencia de escritura. Eso debe ser atrapado bastante rápido durante el desarrollo ...
De todos modos, buen punto, de ahí la edición :)
Se requiere explícitamente una implementación adecuada de Dispose para no importar si se ha invocado más de una vez en el mismo objeto. Mientras que las llamadas múltiples a Descartar son a veces indicativas de problemas lógicos o de un código que podría escribirse mejor, la única forma en que mejoraría el código original publicado sería convencer a Microsoft de que agregue una opción a BinaryReader y BinaryWriter indicándoles que no eliminen sus pases. in stream (y luego use esa opción). De lo contrario, el código requerido para asegurar que el archivo se cierre incluso si el lector o el escritor arroja su constructor sería lo suficientemente feo que simplemente dejar que el archivo se elimine más de una vez parecería más limpio.
Tu escritor dispondrá tu transmisión, siempre.