MDA de streamWriterBufferedDataLost
Nota:
Este artículo es específico de .NET Framework. No se aplica a implementaciones más recientes de .NET, incluidas .NET 6 y versiones posteriores.
El Asistente para la depuración administrada (MDA) streamWriterBufferedDataLost
se activa cuando se escribe un StreamWriter, pero después no se llama al método Flush o Close antes de que se destruya la instancia del StreamWriter. Cuando este MDA está habilitado, el tiempo de ejecución determina si los datos almacenados en búfer todavía existen en StreamWriter. Si existen datos almacenados en búfer, se activa el MDA. Llamar a los métodos Collect y WaitForPendingFinalizers puede forzar la ejecución de los finalizadores. En caso contrario, los finalizadores se ejecutarán en momentos aparentemente arbitrarios y posiblemente no lo hagan en la salida del proceso. La ejecución explícita de los finalizadores con este MDA habilitado ayudará a reproducir este tipo de problema de forma más confiable.
Síntomas
StreamWriter no escribe los últimos 1-4 KB de datos en un archivo.
Causa
StreamWriter almacena en búfer los datos internamente, lo que requiere que se llame al método Close o Flush para escribir los datos almacenados en búfer en el almacén de datos subyacente. Si no se llama a Close o Flush adecuadamente, es posible que los datos almacenados en búfer en la instancia de StreamWriter no se escriban de la forma esperada.
El siguiente es un ejemplo de código mal escrito que este MDA debería detectar.
// Poorly written code.
void Write()
{
StreamWriter sw = new StreamWriter("file.txt");
sw.WriteLine("Data");
// Problem: forgot to close the StreamWriter.
}
El código anterior activará este MDA de una manera más confiable si se desencadena una recolección de elementos no utilizados y después se suspende hasta que hayan terminado los finalizadores. Para realizar un seguimiento de este tipo de problema, puede agregar el código siguiente al final del método anterior en una compilación de depuración. Esto ayudará a activar el MDA de forma confiable, pero por supuesto no soluciona la causa del problema.
GC.Collect();
GC.WaitForPendingFinalizers();
Solución
Asegúrese de que se llama a Close o Flush en StreamWriter antes de cerrar una aplicación o cualquier bloque de código que tenga una instancia de StreamWriter. Uno de los mejores mecanismos para conseguirlo es crear la instancia con un bloque using
de C# (Using
en Visual Basic), que se asegurará de que se invoca el método Dispose para el escritor y, como resultado, la instancia se cerrará correctamente.
using(StreamWriter sw = new StreamWriter("file.txt"))
{
sw.WriteLine("Data");
}
En el código siguiente se muestra la misma solución, usando try/finally
en lugar de using
.
StreamWriter sw;
try
{
sw = new StreamWriter("file.txt"));
sw.WriteLine("Data");
}
finally
{
if (sw != null)
sw.Close();
}
Si ninguna de estas soluciones se pueden usar (por ejemplo, si un StreamWriter se almacena en una variable estática y no se puede ejecutar fácilmente código al final de su duración), llamar a Flush en StreamWriter después de su último uso o establecer la propiedad AutoFlush en true
antes de su primer uso debería evitar este problema.
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;
}
Efecto en el Runtime
Este MDA no tiene ningún efecto en el tiempo de ejecución.
Output
Un mensaje que indica que se produjo esta infracción.
Configuración
<mdaConfig>
<assistants>
<streamWriterBufferedDataLost />
</assistants>
</mdaConfig>