streamWriterBufferedDataLost MDA
注意
本文專屬於 .NET Framework。 它不適用於較新的 .NET 實作,包括 .NET 6 和更新版本。
streamWriterBufferedDataLost
Managed 偵錯助理 (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 呼叫 Close 或 Flush,然後才關閉具有 StreamWriter 執行個體的應用程式或任何程式碼區塊。 達到此目的的其中一個最佳機制,是使用 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 對執行階段沒有影響。
輸出
指出發生此違規的訊息。
組態
<mdaConfig>
<assistants>
<streamWriterBufferedDataLost />
</assistants>
</mdaConfig>