streamWriterBufferedDataLost MDA
streamWriterBufferedDataLost MDA(관리 디버깅 도우미)는 StreamWriter가 기록될 때 활성화되지만 Flush 또는 Close 메서드는 StreamWriter 인스턴스가 소멸되기 전에 계속 호출되지 않습니다. 이 MDA가 사용되면 런타임은 버퍼링된 모든 데이터가 StreamWriter 내에 있는지 여부를 확인합니다. 버퍼링된 데이터가 있으면 MDA가 활성화됩니다. Collect 및 WaitForPendingFinalizers 메서드를 호출하면 종료자를 강제로 실행할 수 있습니다. 이 경우가 아니면 종료자는 프로세스 종료 시가 아니라 무작위로 실행됩니다. 이 MDA를 사용하면서 종료자를 명시적으로 실행하면 좀 더 안정적으로 이 유형의 문제를 재현할 수 있습니다.
증상
StreamWriter가 마지막 1-4KB의 데이터를 파일에 쓰지 않습니다.
원인
StreamWriter는 데이터를 내부적으로 버퍼링하며, Close 또는 Flush 메서드를 호출하여 버퍼링된 데이터를 내부 데이터 저장소에 써야 합니다. Close나 Flush를 적절하게 호출하지 않으면 StreamWriter 인스턴스에 버퍼링된 데이터가 예상대로 기록되지 않을 수 있습니다.
다음은 이 MDA가 catch해야 하는 잘못 작성된 코드 예제입니다.
// Poorly written code.
void Write()
{
StreamWriter sw = new StreamWriter("file.txt");
sw.WriteLine("Data");
// Problem: forgot to close the StreamWriter.
}
가비지 수집이 트리거된 다음 종료자가 종료될 때까지 일시 중단되는 경우 앞의 코드는 이 MDA를 좀 더 안정적으로 활성화합니다. 이 유형의 문제를 추적하려면 다음 코드를 디버그 빌드 시 이전 메서드의 끝에 추가하면 됩니다. 이렇게 하면 MDA를 안정적으로 활성화할 수 있지만 문제의 원인은 해결되지 않습니다.
GC.Collect();
GC.WaitForPendingFinalizers();
해결 방법
StreamWriter 인스턴스가 있는 코드 블록이나 응용 프로그램을 닫기 전에 StreamWriter에 대해 Close나 Flush를 호출해야 합니다. 이를 수행하는 가장 적합한 메커니즘 중 하나는 C# using 블록(Visual Basic의 경우 Using)을 사용하여 인스턴스를 만드는 것이며, 이렇게 하면 작성기에 대해 Dispose 메서드가 반드시 호출되므로 인스턴스가 올바르게 닫힙니다.
using(StreamWriter sw = new StreamWriter("file.txt"))
{
sw.WriteLine("Data");
}
다음 코드에서는 using이 아니라 try/finally를 사용하여 동일한 솔루션을 보여 줍니다.
StreamWriter sw;
try
{
sw = new StreamWriter("file.txt"));
sw.WriteLine("Data");
}
finally
{
if (sw != null)
sw.Close();
}
이러한 솔루션을 사용할 수 없는 경우, 예를 들어 StreamWriter가 정적 변수에 저장되고 수명의 끝에 코드를 쉽게 실행할 수 없는 경우 마지막 사용 후에 StreamWriter에 대해 Flush를 호출하거나 첫 사용 전에 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는 런타임에 아무런 영향을 주지 않습니다.
Output
이 위반이 발생했음을 나타내는 메시지입니다.
구성
<mdaConfig>
<assistants>
<streamWriterBufferedDataLost />
</assistants>
</mdaConfig>