BinaryReader/Writer втихую закрывает MemoryStream.
От: drpadawan  
Дата: 22.10.06 06:55
Оценка:
Данный фрагмент зависает без генерации исключений на последней строке.

...
MemoryStream stream = new MemoryStream(16);
...
using (BinaryWriter bw = new BinaryWriter(stream))
{
stream.WriteByte(0);
}
string len = stream.Length.ToString();

Если убрать using, то не зависает. Причем, будучи выполненным в дочернем thread,
исключений это не генерирует. В родительском thread, генерируется исключение о закрытом
stream. Хотя с чего ради stream закрывается?

Вопрос, если убрать using, то созданный BinaryWriter так и будет висеть? Дело в том, что stream у меня кешируется, а BinaryWriter'ов и Reader'ов куча к нему может прицепляться.
Re: BinaryReader/Writer втихую закрывает MemoryStream.
От: Mab Россия http://shade.msu.ru/~mab
Дата: 22.10.06 09:17
Оценка:
Здравствуйте, drpadawan, Вы писали:

BinaryWriter.Dispose вызывает Close для underlying stream. Если stream планируется использовать дальше, то не ныжно использовать using, вот и все.
Re: BinaryReader/Writer втихую закрывает MemoryStream.
От: GlebZ Россия  
Дата: 22.10.06 09:26
Оценка:
Здравствуйте, drpadawan, Вы писали:

D>Если убрать using, то не зависает. Причем, будучи выполненным в дочернем thread,

D>исключений это не генерирует. В родительском thread, генерируется исключение о закрытом
D>stream. Хотя с чего ради stream закрывается?
В основном он предназначен для работы с unmanaged устройствами.

D>Вопрос, если убрать using, то созданный BinaryWriter так и будет висеть?

Соберется GC — но без вызова Dispose
D>Дело в том, что stream у меня кешируется, а BinaryWriter'ов и Reader'ов куча к нему может прицепляться.
Я бы кэшировал сам буфер byte[]. Создание MemoryStream по буферу очень быстрое, и не будет проблем с позиционированием. Особенно — если у тебя многопоточка.
... << RSDN@Home 1.2.0 alpha rev. 0>>
BinaryReader/Writer втихую закрывает MemoryStream.
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 23.01.07 09:39
Оценка: 7 (1)
#Имя: FAQ.dotnet.BinaryWriterAndMemoryStream
Здравствуйте, drpadawan, Вы писали:

D>Данный фрагмент зависает без генерации исключений на последней строке.


D>...
D>    MemoryStream stream = new MemoryStream(16);
D>...
D>    using (BinaryWriter bw = new BinaryWriter(stream))
D>    {
D>        stream.WriteByte(0);
D>    }
D>    string len = stream.Length.ToString();


D>Если убрать using, то не зависает. Причем, будучи выполненным в дочернем thread,

D>исключений это не генерирует. В родительском thread, генерируется исключение о закрытом
D>stream. Хотя с чего ради stream закрывается?

http://rsdn.ru/res/book/net/richter.xml
Автор(ы): Джеффри Рихтер

В книге подробно описано внутреннее устройство и функционирование общеязыковой исполняющей среды (CLR) Microsoft .NET Framework. Подробно изложена развитая система типов .NET Framework и разъясняются способы управления типами исполняющей средой. Хотя примеры в книге написаны на C#, представленные в ней концепции относятся ко всем языкам, ориентированным на работу с .NET Framework. Книга ориентирована на разработчиков любых видов приложений на платформе .NET Framework: Windows Forms, Web Forms, Web-сервисов, консольных приложений, служб и пр. Предполагается знакомство читателя с основными концепциями объектно-ориентированного программирования и знание языков программирования.
:

Интересная проблема с зависимостью

Тип System.IO.FileStream позволяет пользователю открывать файл для чтения и записи. Для повышения быстродействия тип использует буфер в памяти. Только после заполнения буфера тип сбрасывает его содержимое в файл. Тип FileStream поддерживает только запись байтов — для записи более сложных структур данных (Int32, Double, String и т. д.) используйте тип System.IO.BinaryWriter:

FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write("Hi there");
// Следующий вызов Close обязателен.
bw.Close();
// ПРИМЕЧАНИЕ: Метод BinaryWriter.Close закрывает объект FileStream.
// В этом сценарии не следует закрывать FileStream явно.

Заметьте: конструктор BinaryWriter принимает в качестве параметра ссылку на объект FileStream, которую он сохраняет во внутреннем поле. При записи объект BinaryWriter производит буферизацию данных, используя для этого внутренний буфер в памяти. При заполнении буфера BinaryWriter записывает данные в FileStream.

При записи данных через объект BinaryWriter следует вызывать Dispose или Close (так как в типе BinaryWriter реализована модель освобождения ресурсов, его можно использовать с оператором С# using). Оба эти метода делают одно и то же: заставляют BinaryWriter сбросить данные в объект FileStream и закрыть его. При закрытии объект BinaryWriter сбрасывает свои данные на диск прямо перед вызовом функции Win32 CloseHandle.

Примечание: Вам не обязательно явно вызывать методы Dispose или Close для объекта FileStream: BinaryWriter вызывает их за вас. Если вы все-таки вызвали один из этих методов явно, FileStream увидит, что очистка объекта уже выполнена, и вызванный метод просто вернет управление.

Как вы думаете, что было бы, не будь кода, явно вызывающего Dispose или Close? Сборщик мусора однажды определил бы (и определил правильно), что эти объекты стали мусором, и завершил их. Но он не гарантирует вызов методов Finalize в определенном порядке, поэтому возможны два варианта: если FileStream завершается первым, он закрывает файл, затем при завершении объекта BinaryWriter он попытается записать данные в закрытый файл, чем вызовет исключение. С другой стороны, если BinaryWriter завершается первым, данные будут благополучно записаны в файл.

Как с этой проблемой справились в Microsoft? Заставить сборщик завершить объекты в определенном порядке нельзя, так как в объектах могли быть ссылки друг на друга, и тогда сборщик не сможет угадать правильный порядок их завершения. В Microsoft нашли выход, отказавшись от метода Finalize в типе BinaryWriter.
Это означает, что если вы забыли явно закрыть объект BinaryWriter, то данные гарантированно будут потеряны. В Microsoft ожидают, что разработчики заметят потерю данных и исправят код, вставив явный вызов Close или Dispose.

... << RSDN@Home 1.2.0 alpha rev. 668>>
Re[2]: BinaryReader/Writer втихую закрывает MemoryStream.
От: _FRED_ Черногория
Дата: 23.01.07 10:24
Оценка:
Здравствуйте, GlebZ, Вы писали:

D>>Если убрать using, то не зависает. Причем, будучи выполненным в дочернем thread,

D>>исключений это не генерирует. В родительском thread, генерируется исключение о закрытом
D>>stream. Хотя с чего ради stream закрывается?
GZ>В основном он предназначен для работы с unmanaged устройствами.

Кто? BinaryWriter? Даже если и так, то это его не оправдывает

GZ>Я бы кэшировал сам буфер byte[]. Создание MemoryStream по буферу очень быстрое, и не будет проблем с позиционированием. Особенно — если у тебя многопоточка.


+1
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[3]: BinaryReader/Writer втихую закрывает MemoryStream.
От: GlebZ Россия  
Дата: 24.01.07 12:00
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Кто? BinaryWriter? Даже если и так, то это его не оправдывает

Почему. вполне оправдывает. У тебя есть выбор — закрывать или не закрывать. Это в документации описано. Определяется наличием вызова Dispose. Это поведение всех reader/writer. Почему, Odi$$ey не поленился описать. Конечно, если бы был параметр closeable как в конструкторе StreamReader/StreamWriter — это поведение было бы более явным.
Re[4]: BinaryReader/Writer втихую закрывает MemoryStream.
От: _FRED_ Черногория
Дата: 24.01.07 12:17
Оценка:
Здравствуйте, GlebZ, Вы писали:

_FR>>Кто? BinaryWriter? Даже если и так, то это его не оправдывает

GZ>Почему. вполне оправдывает. У тебя есть выбор — закрывать или не закрывать. …

Я имел в виду "unmanaged устройства".
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[5]: BinaryReader/Writer втихую закрывает MemoryStream.
От: GlebZ Россия  
Дата: 25.01.07 06:27
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Я имел в виду "unmanaged устройства".

А я имел ввиду Dispose.
... << RSDN@Home 1.2.0 alpha rev. 0>>
BinaryReader/Writer втихую закрывает MemoryStream.
От: Аноним  
Дата: 24.01.07 15:32
Оценка:
не используй using, вызывай stream.Close() вручную тогда когда тебе это удобно.
Любое удобство идет за счет мегагерцеф! : {<b>1</b>, <b>2</b>, <b>3</b>, 4, 5}


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.