streamWriterBufferedDataLost MDA
在 StreamWriter 的執行個體毀壞之前,已寫入 StreamWriter,但是未接著呼叫 Flush 或 Close 方法時,即會啟動 streamWriterBufferedDataLost Managed 偵錯助理 (MDA)。 當這個 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");
}
下列程式碼將示範相同的解決方法,其中會使用 try/finally,而非 using。
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>