C# 流在流写入同一文件后立即读取该文件
给定此示例代码:C# 流在流写入同一文件后立即读取该文件,c#,streamreader,race-condition,streamwriter,C#,Streamreader,Race Condition,Streamwriter,给定此示例代码: 1: using (StreamWriter sw = new StreamWriter(@"C:\file.txt")) 2: { 3: sw.WriteLine(great_string); 4: } 5: 6: using (StreamReader sr = new StreamReader(@"C:\file.txt")) 7: { 8: sr.ReadToEnd(); 9: } 当在第8行调用StreamReader
1: using (StreamWriter sw = new StreamWriter(@"C:\file.txt"))
2: {
3: sw.WriteLine(great_string);
4: }
5:
6: using (StreamReader sr = new StreamReader(@"C:\file.txt"))
7: {
8: sr.ReadToEnd();
9: }
当在第8行调用StreamReader.ReadToEnd
时,第3行中写入的great\u字符串是否可能不在C:\file.txt
中?在我看来,这是可能的,因为平均CPU的工作速度比平均HDD快得多,但我今天一直在测试,到目前为止,当我在第8行读取文件时,第3行上写的字符串始终存在。我在想,在文件中写入/读取所有数据之前,using
语句可能不会关闭流,从而防止了我所询问的那种情况
我一直在读MSDN上的方法,它说明如下:
您必须调用Close以确保所有数据都正确地写入底层流
但它没有说明数据何时将被写入底层流
提前感谢您提供有关此主题的任何信息。我确实搜索了这个问题的答案,但没有找到任何答案……我真的不知道要搜索什么术语。您应该使用它,它确保了数据的写入
我在想也许using语句不会关闭流
直到所有数据都写入/读取文件,因此
防止我所问的那种情况
没错。使用()确保对象已完全释放。有关using语句的更多信息,请参阅
也就是说,在关闭文件之前,它的数据将被清除。实际上,它将等待文件被写入。调用Close后,数据可能不会实际出现在硬盘上,但系统(windows内核)将显示它的外观。重要的是外表
如果您从刚写入的文件中读取,Windows将询问HDD或从缓存中提供服务
如果不是这样的话,就很难编写可靠的程序,因为效果的顺序可以在函数甚至进程之间任意改变。那将是一片混乱。因此,系统保证了顺序一致性
仔细想想:如果不存在此序列化属性,则文件可能同时包含多个内容!第一次读它,你就会看到旧的内容。再读一遍,你会突然看到一些变化。幸运的是,这种行为是不可能的。小巷杰克的回答是正确的。观看计时:
static void Main()
{
var file = @"c:\temp\test.bin";
String huge = new String(new char[20 * 1024 * 1024]);
var sw = new Stopwatch();
var sw2 = new Stopwatch();
sw.Start();
using (var stream = new StreamWriter(file))
{
sw2.Start();
stream.Write(huge);
sw2.Stop();
}
sw.Stop();
sw2.Stop();
Console.WriteLine("Write 20MB to cache: " + (sw.Elapsed.TotalMilliseconds - sw2.Elapsed.TotalMilliseconds));
Console.WriteLine("Write 20MB from cache to HD: " + sw2.Elapsed.TotalMilliseconds);
}
输出:
Write 20MB to cache: 5 // ms (including preparing the stream)
Write 20MB from cache to HD: 186 // ms
整个过程是阻塞(同步)。否!冲洗不适用于此用途。在100%的情况下,关闭是完全不可能的。刷新导致缓存被刷新并导致磁盘搜索。@usr:在那里冷却喷射器Dispose
调用Flush
,不管您喜欢与否(并且Close
只调用Dispose(true)
),Dispose不调用Flush。您误读了反射的代码。它调用刷新FileStream内部缓冲区的FlushWrite。它不建议操作系统物理刷新并导致磁盘“fsync”。;meta point:给同花顺打电话是常见的错误建议,我会尽可能地采取行动。有些人建议调用Close、Flush、Dispose,然后关闭using块。这太疯狂了。@usr:我们甚至都没在谈论同一件事。关于FileStream
,您是正确的,这是StreamWriter
基于问题中调用的构造函数将使用的。我只看了StreamWriter
本身,它对任何流调用Flush
。老实说,FileStream
比我想看的要多,因为它的刷新机制非常广泛。@MatthewFerreira你说得对。我还记得我被咬过。我被迫围绕流编写一个包装器类,以防止StreamWriter刷新底层流!这是一个非常讨厌的性能缺陷,在某些性能测试中很容易被注意到。“如果不是这样,就很难编写可靠的程序,因为效果的顺序可能会在函数甚至进程之间任意改变。这将是一个混乱的状态。因此,系统保证顺序的一致性。”---我心里也在想一件类似的事情,但我不知道怎么表达。谢谢,这很有帮助。谢谢你写这篇文章。我刚刚运行了这段代码,其差异(正如您在输出中所显示的)非常大,但并不令人惊讶。能够看到差别有多大是很酷的。