Udostępnij za pośrednictwem


streamWriterBufferedDataLost MDA

Uwaga

Ten artykuł jest specyficzny dla programu .NET Framework. Nie ma zastosowania do nowszych implementacji platformy .NET, w tym .NET 6 i nowszych wersji.

Asystent streamWriterBufferedDataLost zarządzanego debugowania (MDA) jest aktywowany, gdy StreamWriter element jest zapisywany, ale Flush metoda or Close nie jest następnie wywoływana przed zniszczeniem wystąpienia StreamWriter obiektu . Po włączeniu tego rozwiązania MDA środowisko uruchomieniowe określa, czy jakiekolwiek buforowane dane nadal istnieją w obiekcie StreamWriter. Jeśli dane buforowane istnieją, aktywacja MDA zostanie aktywowana. Collect Wywołanie metod i WaitForPendingFinalizers może wymusić uruchamianie finalizatorów. Finalizatory w przeciwnym razie będą działać w pozornie dowolnych godzinach i prawdopodobnie w ogóle nie po zakończeniu procesu. Jawne uruchamianie finalizatorów z włączonym rozwiązaniem MDA pomoże bardziej niezawodnie odtworzyć ten typ problemu.

Objawy

Element A StreamWriter nie zapisuje danych z ostatnich 1–4 KB do pliku.

Przyczyna

Dane StreamWriter buforowane wewnętrznie, co wymaga Close wywołania metody lub Flush w celu zapisania buforowanych danych do bazowego magazynu danych. Jeśli Close lub Flush nie jest odpowiednio wywoływana, dane buforowane w wystąpieniu StreamWriter mogą nie być zapisywane zgodnie z oczekiwaniami.

Poniżej przedstawiono przykład źle napisanego kodu, który powinien przechwycić to rozwiązanie MDA.

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

Powyższy kod aktywuje tę usługę MDA bardziej niezawodnie, jeśli zostanie wyzwolone odzyskiwanie pamięci, a następnie wstrzymane do momentu zakończenia finalizatorów. Aby wytropić ten typ problemu, możesz dodać następujący kod na końcu poprzedniej metody w kompilacji debugowania. Pomoże to w niezawodnej aktywacji mdA, ale oczywiście nie rozwiąże przyczyny problemu.

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

Rozwiązanie

Przed zamknięciem aplikacji lub dowolnego bloku kodu, który ma wystąpienie StreamWriterobiektu , upewnij się, że wywołano Close metodę lub Flush na StreamWriter obiekcie . Jednym z najlepszych mechanizmów osiągnięcia tego celu jest utworzenie wystąpienia z blokiem języka C# using (Using w Visual Basic), co zapewni Dispose wywołanie metody modułu zapisywania, co spowoduje poprawne zamknięcie wystąpienia.

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

Poniższy kod przedstawia to samo rozwiązanie, przy użyciu polecenia try/finally zamiast using.

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

Jeśli nie można użyć żadnego z tych rozwiązań (na przykład jeśli element StreamWriter jest przechowywany w zmiennej statycznej i nie można łatwo uruchomić kodu pod koniec okresu istnienia), wywołaj Flush metodę po StreamWriter jej ostatnim użyciu lub ustawienie AutoFlush właściwości na przed true jej pierwszym użyciem powinno uniknąć tego problemu.

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

Wpływ na środowisko uruchomieniowe

Ta usługa MDA nie ma wpływu na środowisko uruchomieniowe.

Wyjście

Komunikat wskazujący, że to naruszenie miało miejsce.

Konfigurowanie

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

Zobacz też