Freigeben über


streamWriterBufferedDataLost-MDA

Hinweis

Dieser Artikel gilt für das .NET Framework. Sie gilt nicht für neuere Implementierungen von .NET, einschließlich .NET 6 und höherer Versionen.

Der streamWriterBufferedDataLost-MDA (Assistent für verwaltetes Debuggen) wird aktiviert, wenn eine StreamWriter geschrieben wird, aber die Flush- oder Close-Methode wird anschließend nicht aufgerufen, bevor die Instanz der StreamWriter zerstört wird. Wenn dieser MDA aktiviert ist, überprüft die Common Language Runtime, ob gepufferte Daten immer noch in StreamWriter vorhanden sind. Wenn die gepufferten Daten vorhanden sind, wird der MDA aktiviert. Ein Aufruf der Collect- und WaitForPendingFinalizers-Methoden kann erzwingen, dass Finalizer ausgeführt werden. Finalizer werden andernfalls zu scheinbar willkürlichen Zeiten und beim Beenden des Prozesses möglicherweise gar nicht ausgeführt. Wenn Finalizer explizit mit diesem aktiven MDA ausgeführt werden, wird diese Art von Problemen zuverlässiger reproduziert werden können.

Symptome

Ein StreamWriter schreibt die letzten 1 bis 4 KB Daten nicht in eine Datei.

Ursache

Die StreamWriter puffert Daten intern. Dies erfordert, dass die Close- oder Flush-Methode aufgerufen wird, um die gepufferten Daten in den zugrunde liegenden Datenspeicher zu schreiben. Wenn Close oder Flush nicht richtig aufgerufen werden, können gepufferte Daten in der StreamWriter-Instanz nicht wie erwartet geschrieben werden.

Das folgende Beispiel zeigt schlecht geschriebenen Code, den dieser MDA abfangen sollte.

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

Der vorangehende Code wird diesen MDA zuverlässiger aktivieren, wenn eine Garbage Collection ausgelöst und dann angehalten wurde, bis die Finalizer beendet wurden. Um diese Art von Problemen aufzufinden, können Sie den folgenden Code am Ende der vorherigen Methode in einem Debugbuild hinzufügen. Dies hilft dabei, den MDA zuverlässig zu aktivieren, aber natürlich wird die Ursache des Problems somit nicht behoben.

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

Lösung

Stellen Sie sicher, dass Sie Close oder Flush der StreamWriter oder eines beliebigen Codeblocks abrufen, der eine StreamWriter-Instanz enthält, bevor Sie eine Anwendung schließen. Eine der besten Mechanismen, um dies zu erreichen, ist das Erstellen der Instanz mithilfe des using-C#-Blocks (Using in Visual Basic), was sicherstellt, dass die Dispose-Methode für den Writer aufgerufen wurde, wodurch die Instanz ordnungsgemäß geschlossen wird.

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

Der folgende Code zeigt dieselbe Projektmappe mithilfe von try/finally anstelle von using an.

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

Wenn keine dieser Lösungen verwendet werden kann (z.B. wenn sich ein StreamWriter in einer statischen Variablen befindet und Sie den Code am Ende der Lebenszeit nicht problemlos ausführen können), sollte der Aufruf von Flush auf StreamWriter nach der letzten Verwendung oder die Einstellung der AutoFlush-Eigenschaft auf true vor der ersten Verwendung dieses Problem vermeiden.

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

Auswirkungen auf die Laufzeit

Dieser MDA hat keine Auswirkungen auf die Laufzeit.

Output

Eine Meldung, die angibt, dass diese Überschreitung aufgetreten ist.

Konfiguration

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

Siehe auch