streamWriterBufferedDataLost MDA
Note
この記事は .NET Framework に固有のものです。 .NET 6 以降のバージョンを含む、.NET の新しい実装には適用されません。
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 を呼び出します。 これを最も効率的に行う方法は、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>
関連項目
.NET