我遇到了一个问题,即我在执行文件写入操作时会出现大量(10秒以上)延迟。它似乎只发生一次,并且总是发生在对WriteToFile()函数的第二次(或有时是第三次?)调用期间。
我已经写出了3个不同的WriteToFile'功能显示我到目前为止尝试过的一些变化+在OpenFileIfNecessary' OpenFileIfNecessary'我试过了。
代码永远不会抛出错误,并且偏移/计数都是有效的。一旦延迟发生一次,似乎没有进一步的延迟。
这对我来说是一个痛苦的2天以上,我肯定在那个时候我需要第二意见。
private void WriteToFile(byte[] data, long offset, int count)
{
lock (this.monitor)
{
this.OpenFileIfNecessary();
this.fileStream.Seek(offset, SeekOrigin.Begin); // <- Takes 10+ seconds for THIS line to execute
this.fileStream.Write(data, 0, count);
}
}
private void WriteToFile2(byte[] data, long offset, int count)
{
lock (this.monitor)
{
this.OpenFileIfNecessary();
this.fileStream.Position = offset; // <- Takes 10+ seconds for THIS line to execute
this.fileStream.Write(data, 0, count);
}
}
private void WriteToFile3(byte[] data, long offset, int count)
{
lock (this.monitor)
{
var fileName = this.file.FullName;
using (Stream fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
{
fileStream.Position = offset; //(instant execution of this line)
fileStream.Write(data, 0, count);
//Getting from HERE ->
}
//To HERE <- takes 10+ seconds
}
}
private System.IO.FileStream fileStream = null;
private System.IO.FileInfo file; //value set during construction
private void OpenFileIfNecessary()
{
lock (this.monitor) {
if (this.fileStream == null) {
//The following 3 lines all result in the same behavior described in this post
//this.fileStream = this.file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
//this.fileStream = this.file.Open(FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
//this.fileStream = this.file.OpenWrite();
this.fileStream = this.file.Open(FileMode.OpenOrCreate);
}
}
}
答案 0 :(得分:1)
发现了这个问题。值得一提的是,我们之前一直在测试较小的(<1GB文件)直到上周末。考虑到这一点:
我们在不同的位置写文件,也就是说,我们不是从0位开始直到结束。这意味着什么(特别是对于较大的文件)是每次我们第一次进入文件深处的位置时,显然有一个等待时间段来分配新扩展的大小。
FileStream混淆了很多底层内容的方式使得查找模式变得有点困难,一旦我们进行了更深入的分析并发现较小的文件(从未注意到之前的延迟),它就变得更小了清楚发生了什么。
计划转发是做一些多线程以允许在写入磁盘之前完全分配文件的空间;我们可以在等待期间缓冲内存。
预分配整个文件的示例代码:
fileStream.Seek(size - 1, SeekOrigin.Begin);
fileStream.WriteByte(0);
fileStream.Flush();
答案 1 :(得分:0)
这种情况正在发生,因为当您将文件位置设置为某个较大的值时,底层存储系统必须将已分配块的内容清零。我不相信BCL会让你绕过它但是在Win32中实际上有一种方法可以跳过这个需要运行程序来拥有管理员权限的功能(以非常不精确的方式)。
搜索SetFileValidData()文档。