streamWriterBufferedDataLost MDA

streamWriterBufferedDataLost マネージド デバッグ アシスタント (MDA) は StreamWriter が書き込まれたときに起動しますが、その後、StreamWriter のインスタンスが破棄される前に Flush または Close メソッドが呼び出されません。 この MDA が有効になると、バッファーに入れられたデータが StreamWriter 内に残っているか、ランタイムにより判断されます。 バッファーに入れられたデータが残っている場合、MDA が起動します。 Collect メソッドと WaitForPendingFinalizers メソッドを呼び出すことで、ファイナライザーを強制的に実行できます。 それ以外の場合、ファイナライザーは任意のタイミングで実行されます。プロセス終了時に実行されることは、ほぼありません。 この MDA が有効になっている状態でファイナライザーを明示的に実行すると、この種類の問題をより確実に再現できます。

現象

StreamWriter では、最後の 1 – 4 KB のデータがファイルに書き込まれません。

原因

StreamWriter はデータを内部でバッファーに入れます。このとき、Close または Flush メソッドを呼び出し、バッファーに入れたデータを基礎となるデータ ストアに書き込む必要があります。 Close または Flush が正しく呼び出されない場合、StreamWriter インスタンスのバッファーに入れられたデータは予想どおりに書き込まれないことがあります。

次は、この MDA がキャッチする、書き込みが十分ではないコードの例です。

// 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 のインスタンスが含まれるコード ブロックを終了する前に、StreamWriterClose または 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 が静的変数に保存されており、その有効期間の終わりにコードを実行することが簡単でない場合など)、最後に使用した後で StreamWriterFlush を呼び出すか、最初に使用する前に 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 は、ランタイムに影響しません。

出力

この違反が発生したことを示すメッセージ

構成

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

関連項目