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


streamWriterBufferedDataLost MDA

Примечание.

Эта статья относится к .NET Framework. Он не применяется к более новым реализациям .NET, включая .NET 6 и более поздние версии.

Помощник по отладке управляемого кода (MDA) streamWriterBufferedDataLost активируется при записи в StreamWriter, если методы Flush или Close после этого не вызываются до уничтожения экземпляра StreamWriter. Если этот помощник по отладке управляемого кода включен, среда выполнения определяет, существуют ли до сих пор какие-либо буферизованные данные в StreamWriter. Если буферизованные данные существуют, помощник по отладке управляемого кода активируется. Вызов методов Collect и WaitForPendingFinalizers может принудительно вызвать методы завершения. В противном случае методы завершения будут выполняться в произвольные моменты времени и, возможно, вовсе не в момент завершения работы процесса. Выполнение методов завершения явным образом, когда данный помощник по отладке управляемого кода включен, способствует более надежному воспроизведению проблемы такого типа.

Симптомы

StreamWriter не записывает последние 1–4 КБ данных в файл.

Причина

StreamWriter осуществляет внутреннюю буферизацию данных. Для этого требуется, чтобы метод Close или Flush вызывался для записи буферизованных данных в базовое хранилище данных. Если метод Close или Flush не вызывается должным образом, данные, буферизованные в экземпляре StreamWriter, возможно, будут записаны некорректно.

Ниже приведен пример неправильно написанного кода, который помощник по отладке управляемого кода должен перехватить.

// Poorly written code.
void Write()
{
    StreamWriter sw = new StreamWriter("file.txt");
    sw.WriteLine("Data");
    // Problem: forgot to close the StreamWriter.
}

Предыдущий код активирует помощник по отладке управляемого кода более надежно, если сборка мусора запускается, а затем останавливается до того, как закончат работу методы завершения. Чтобы отследить проблему такого типа, можно добавить приведенный ниже код в конец предыдущего метода в отладочной сборке. Это поможет уверенно активировать этот помощник по отладке управляемого кода, но, конечно, не устранит причины возникновения проблемы.

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;
}

Влияние на среду выполнения

Этот MDA не оказывает никакого влияния на среду выполнения.

Выходные данные

Сообщение о том, что произошло данное нарушение.

Настройка

<mdaConfig>
  <assistants>
    <streamWriterBufferedDataLost />
  </assistants>
</mdaConfig>

См. также