Здравствуйте, 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>>
Автор: Odi$$ey    Оценить