Поделиться через


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>

См. также

Основные понятия

Диагностика ошибок посредством управляемых помощников по отладке

Ссылки

StreamWriter