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刷新底层流!这是一个非常讨厌的性能缺陷,在某些性能测试中很容易被注意到。“如果不是这样,就很难编写可靠的程序,因为效果的顺序可能会在函数甚至进程之间任意改变。这将是一个混乱的状态。因此,系统保证顺序的一致性。”---我心里也在想一件类似的事情,但我不知道怎么表达。谢谢,这很有帮助。谢谢你写这篇文章。我刚刚运行了这段代码,其差异(正如您在输出中所显示的)非常大,但并不令人惊讶。能够看到差别有多大是很酷的。