注释
本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。
当streamWriterBufferedDataLost写入托管调试助手(MDA),但在销毁实例StreamWriter之前不会调用托管调试助手(MDA),StreamWriter但Flush随后不会调用该方法Close。 启用此 MDA 后,运行时将确定任何缓冲数据是否仍存在于其中 StreamWriter。 如果缓冲数据存在,则会激活 MDA。
Collect调用和WaitForPendingFinalizers方法可以强制终结器运行。 终结器将在看似任意的时间运行,在进程退出时可能根本不会运行。 显式运行启用了此 MDA 的终结器将有助于更可靠地重现此类问题。
症状
A 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或FlushStreamWriter打开 。 实现此目的的最佳机制之一是使用 C# using 块(Using 在 Visual Basic 中)创建实例,这将确保 Dispose 调用编写器的方法,从而导致实例正确关闭。
using(StreamWriter sw = new StreamWriter("file.txt"))
{
sw.WriteLine("Data");
}
以下代码显示了同一解决方案,而不是try/finallyusing使用 。
StreamWriter sw;
try
{
sw = new StreamWriter("file.txt"));
sw.WriteLine("Data");
}
finally
{
if (sw != null)
sw.Close();
}
如果这两个解决方案都不能使用(例如,如果 a StreamWriter 存储在静态变量中,并且无法在生存期结束时轻松运行代码),则调用FlushStreamWriter其上次使用之后或将属性true设置为AutoFlush在首次使用之前应避免此问题。
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>