MDA de streamWriterBufferedDataLost

Actualización: noviembre 2007

El asistente para la depuración administrada (MDA) streamWriterBufferedDataLost se activa cuando se escribe en StreamWriter, pero no se llama subsecuentemente al método Flush o Close antes de destruir la instancia de StreamWriter. Cuando este MDA está habilitado, el motor en tiempo de ejecución determina si todavía existen datos almacenados en búfer dentro del escritor StreamWriter. Si existen datos almacenados en búfer, se activa el MDA. Llamar a los métodos Collect y WaitForPendingFinalizers puede obligar a que se ejecuten los finalizadores. De lo contrario, los finalizadores ejecutarán en momentos aparentemente arbitrarios y posiblemente no se ejecuten al salir del proceso. Ejecutar explícitamente los finalizadores con este MDA habilitado ayudará a reproducir este tipo de problema con más confiabilidad.

Síntomas

Un StreamWriter no escribe los últimos 1–4 KB de datos en un archivo.

Motivo

El escritor StreamWriter almacena internamente los datos en el búfer, 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 adecuadamente a Close o a Flush, los datos almacenados en búfer en la instancia de StreamWriter podrían no escribirse de la manera esperada.

Lo siguiente es un ejemplo de código deficientemente escrito que debería detectar este MDA.

// 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 con más seguridad si se desencadena una recolección de elementos no utilizados y, a continuación, quedará en suspenso hasta que hayan terminado los finalizadores. Para encontrar este tipo de problema, puede agregar el código siguiente al final del método anterior en una versión de depuración. Esto ayudará a activar el MDA con seguridad, pero desde luego no corrige la causa del problema.

    GC.Collect();
    GC.WaitForPendingFinalizers();

Resolución

Asegúrese de llamar a Close o a Flush en el StreamWriter antes de cerrar una aplicación o cualquier bloque de código que tenga una instancia de un escritor StreamWriter. Uno de los mejores mecanismos de conseguir este objetivo consiste en crear la instancia con un bloque using de C# (Using en Visual Basic), que garantizará que se llamará al método Dispose del escritor, de manera que la instancia se cerrará correctamente.

using(StreamWriter sw = new StreamWriter("file.txt")) 
{
    sw.WriteLine("Data");
}

El código siguiente muestra la misma solución, utilizando try/finally en lugar de using.

StreamWriter sw;
try 
{
    sw = new StreamWriter("file.txt"));
    sw.WriteLine("Data");
}
finally 
{
    if (sw != null)
        sw.Close();
}

Si no se puede usar ninguna de estas soluciones (por ejemplo, si se almacena StreamWriter en una variable estática y no es fácil ejecutar código al final de su período de duración), este problema podría evitarse llamando a Flush de StreamWriter después de su última utilización o establecer la propiedad AutoFlush en true antes de usarlo por primera vez.

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 tiempo de ejecución

Este MDA no tiene ningún efecto en tiempo de ejecución.

Resultados

Un mensaje que indica que se produjo esta infracción.

Configuración

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

Vea también

Conceptos

Diagnóstico de errores con ayudantes de depuraciones administradas

Referencia

StreamWriter