共用方式為


streamWriterBufferedDataLost MDA

注意

本文專屬於 .NET Framework。 它不適用於較新的 .NET 實作,包括 .NET 6 和更新版本。

streamWriterBufferedDataLost Managed 偵錯助理 (MDA) 會在寫入 StreamWriter 時啟動,但在終結 StreamWriter 的執行個體之前,不會接著呼叫 FlushClose 方法。 此 MDA 啟用時,執行階段會判斷在 StreamWriter 內是否仍有任何緩衝資料存在。 如果緩衝資料不存在,則會啟動 MDA。 呼叫 CollectWaitForPendingFinalizers 方法可以強制執行完成項。 否則完成項會在任意時間執行,並且可能根本不是在處理序結束時。 明確執行完成項並啟用這個 MDA,可協助您更可靠地重現這種類型的問題。

徵兆

StreamWriter 不會將資料的最後 1–4 KB 寫入至檔案。

原因

StreamWriter 會在內部緩衝處理資料,這樣需要呼叫 CloseFlush 方法以將緩衝資料寫入基礎資料存放區。 如果 CloseFlush 未適當地呼叫,則 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 呼叫 CloseFlush,然後才關閉具有 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>

另請參閱