Подтвердить что ты не робот

"Объект может быть удален более одного раза" ошибка

Когда я запускаю анализ кода на следующем фрагменте кода, я получаю это сообщение:

Объект "поток" может быть удален более чем один раз в методе "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);
    }
}

Я не понимаю, почему его можно вызвать дважды, и как его устранить, чтобы устранить ошибку. Любая помощь?

4b9b3361

Ответ 1

Чтобы проиллюстрировать, отредактируйте свой код

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: чтобы принять во внимание то, что говорит Эрик Липперт, действительно может быть момент, когда поток будет выпущен только финализатором, если 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
  • если вы не указали вывод, т.е. если поток имеет значение null. Это не должно быть проблемой, поскольку нулевой поток означает отсутствие ресурсов для утилизации:)
  • если вы не указали кодировку. так как мы не используем конструкторную форму, в которой указано кодирование, здесь также не должно быть проблем (я не слишком много смотрел на конструктор кодировки, но некорректная кодовая страница может вызывать)
    • если вы не передаете поток, доступный для записи. Это нужно быстро поймать во время разработки...

В любом случае, хорошая точка, следовательно, редактирование:)

Ответ 2

Я боролся с этой проблемой и нашел пример здесь, чтобы быть очень полезным. Я отправлю код для быстрого просмотра:

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

Замените внешнюю инструкцию using try/finally, убедившись, что BOTH обнуляет поток после его использования в StreamWriter. И проверьте, чтобы он не был нулевым в конце перед удалением.

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();
}

Выполнение этих ошибок устранено.

Ответ 3

BinaryReader/BinaryWriter будет располагать базовый поток для вас, когда он располагает. Вам не нужно делать это явно.

Чтобы исправить это, вы можете удалить использование вокруг самого потока.

Ответ 4

Правильная реализация Dispose явно требуется не заботиться о том, что она была вызвана более одного раза на одном и том же объекте. В то время как несколько вызовов Dispose иногда указывают на логические проблемы или код, которые могут быть лучше написаны, единственный способ улучшить исходный размещенный код - убедить Microsoft добавить параметр BinaryReader и BinaryWriter, инструктирующий их не распоряжаться переданными данными, в потоке (и затем используйте эту опцию). В противном случае код, необходимый для обеспечения закрытия файла, даже если читатель или писатель бросает его конструктор, будет достаточно уродливым, что просто позволить файлу удаляться более чем один раз будет казаться более чистым.

Ответ 5

Ваш писатель всегда будет располагать ваш поток.