streamWriterBufferedDataLost MDA
Обновлен: Ноябрь 2007
Управляемый помощник по отладке (MDA) streamWriterBufferedDataLost активируется при записи в StreamWriter, но методы Flush или Close после этого не вызываются до уничтожения экземпляра StreamWriter. Если данный MDA включен, среда выполнения определяет, существуют ли до сих пор какие-либо буферизованные данные в StreamWriter. Если буферизованные данные существуют, MDA активируется. Вызов методов Collect и WaitForPendingFinalizers может принудительно вызвать метод завершения. В других случаях методы завершения будут выполняться в произвольные моменты времени, и, возможно, вовсе не в момент завершения работы процесса. Выполнение методов завершения явным образом, когда данный MDA включен, способствует более надежному воспроизведению проблемы такого типа.
Признаки
StreamWriter не записывает последние 1-4 КБ данных в файл.
Причина
StreamWriter буферизует данные внутренне; для этого требуется, чтобы методы Close или Flush вызывались для записи буферизованных данных в основное хранилище данных. Если Close или Flush не вызываются должным образом, данные, буферизованные в экземпляре StreamWriter, возможно, будут записаны некорректно.
Далее приведен пример некорректно написанного кода, который MDA должен перехватить:
// Poorly written code.
void Write()
{
StreamWriter sw = new StreamWriter("file.txt");
sw.WriteLine("Data");
// Problem: forgot to close the StreamWriter.
}
Предыдущий код активирует данный MDA более надежно, если коллекция мусора запущена и затем остановлена до того, как завершат работу методы завершения. Чтобы отследить проблему такого типа, можно добавить следующий код в конец предыдущего метода в отладочном построении. Это поможет уверенно активировать этот MDA, но, конечно, не устранит причины возникновения проблемы.
GC.Collect();
GC.WaitForPendingFinalizers();
Решение
Следует обязательно вызывать Close или Flush на StreamWriter прежде, чем закрыть приложение или любой блок кода, в котором есть экземпляр StreamWriter. Добиться этого проще всего с помощью создания экземпляра с блоком C# using (Using в Visual Basic), что обеспечивает вызов метода Dispose для средства записи, в результате чего экземпляр закрывается корректно.
using(StreamWriter sw = new StreamWriter("file.txt"))
{
sw.WriteLine("Data");
}
Следующий пример кода демонстрирует то же самое решение, но при помощи try/finally вместо using:
StreamWriter sw;
try
{
sw = new StreamWriter("file.txt"));
sw.WriteLine("Data");
}
finally
{
if (sw != null)
sw.Close();
}
Если невозможно использовать ни одно из этих решений (например, если StreamWriter хранится в статической переменной, и нельзя просто запустить код в конце его времени существования), в таком случае можно избежать возникновения данной проблемы, вызвав Flush для StreamWriter после его последнего использования и присвоив свойству AutoFlush значение true перед его первым использованием.
private static StreamWriter log;
// static class constructor.
static WriteToFile()
{
StreamWriter sw = new StreamWriter("log.txt");
sw.AutoFlush = true;
// Publish the StreamWriter for other threads.
log = sw;
}
Влияние на среду выполнения
Данный помощник по отладке управляемого кода не оказывает влияния на среду CLR.
Результат
Сообщение о том, что произошло данное нарушение.
Конфигурация
<mdaConfig>
<assistants>
<streamWriterBufferedDataLost />
</assistants>
</mdaConfig>
См. также
Основные понятия
Диагностика ошибок посредством управляемых помощников по отладке