Данный фрагмент зависает без генерации исключений на последней строке.
...
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'ов куча к нему может прицепляться.
Здравствуйте, drpadawan, Вы писали:
D>Если убрать using, то не зависает. Причем, будучи выполненным в дочернем thread, D>исключений это не генерирует. В родительском thread, генерируется исключение о закрытом D>stream. Хотя с чего ради stream закрывается?
В основном он предназначен для работы с unmanaged устройствами.
D>Вопрос, если убрать using, то созданный BinaryWriter так и будет висеть?
Соберется GC — но без вызова Dispose D>Дело в том, что stream у меня кешируется, а BinaryWriter'ов и Reader'ов куча к нему может прицепляться.
Я бы кэшировал сам буфер byte[]. Создание MemoryStream по буферу очень быстрое, и не будет проблем с позиционированием. Особенно — если у тебя многопоточка.
Здравствуйте, 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 закрывается?
Тип 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.
Здравствуйте, 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.
Здравствуйте, _FRED_, Вы писали:
_FR>Кто? BinaryWriter? Даже если и так, то это его не оправдывает
Почему. вполне оправдывает. У тебя есть выбор — закрывать или не закрывать. Это в документации описано. Определяется наличием вызова Dispose. Это поведение всех reader/writer. Почему, Odi$$ey не поленился описать. Конечно, если бы был параметр closeable как в конструкторе StreamReader/StreamWriter — это поведение было бы более явным.
Здравствуйте, 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.