streamWriterBufferedDataLost MDA
更新 : 2007 年 11 月
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>