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 のインスタンスを持つアプリケーションまたはコード ブロックを閉じる前に、StreamWriter で Close または Flush を呼び出します。 これを実現する最良の機構の 1 つが、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 は、ランタイムに影響しません。
出力
この違反が発生したことを示すメッセージ
構成
<mdaConfig>
<assistants>
<streamWriterBufferedDataLost />
</assistants>
</mdaConfig>