一些背景:我一直在试验在处理大文件时使用FILE_FLAG_NO_BUFFERING标志。我们正在努力减少缓存管理器的负载,希望通过后台IO,我们将减少应用程序对用户计算机的影响。性能不是问题。尽可能多地躲在幕后是个大问题。我有一个非常接近工作的包装程序来执行未缓冲的IO,但我遇到了一个奇怪的问题。当我用一个不是4的倍数的偏移量调用Read时,我会得到这个错误。
句柄不支持同步操作。可能需要更改FileStream构造函数的参数,以指示句柄是异步打开的(也就是说,它是为重叠的I/O显式打开的)。
这一切为什么要发生?这个信息不是自相矛盾吗?如果添加异步文件选项,就会得到一个IOException(参数不正确)。
我想真正的问题是,http://msdn.microsoft.com/en-us/library/windows/desktop/cc644950%28v=vs.85%29.aspx,这些需求与4的倍数有什么关系?
下面是演示这个问题的代码:
FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;
int MinSectorSize = 512;
byte[] buffer = new byte[MinSectorSize * 2];
int i = 0;
while (i < MinSectorSize)
{
try
{
using (FileStream fs = new FileStream(@"<some file>", FileMode.Open, FileAccess.Read, FileShare.None, 8, FileFlagNoBuffering | FileOptions.Asynchronous))
{
fs.Read(buffer, i, MinSectorSize);
Console.WriteLine(i);
}
}
catch { }
i++;
}
Console.ReadLine();发布于 2012-09-11 22:36:46
在使用FILE_FLAG_NO_BUFFERING时,文档中的要求是读或写的内存地址必须是物理扇区大小的倍数。在代码中,允许随机选择字节数组的地址(因此不太可能是物理扇区大小的倍数),然后添加偏移量。
您所观察到的行为是,如果偏移量为4的倍数,则调用工作。字节数组很可能与4字节的边界对齐,因此如果内存地址为4的倍数,则调用工作。
因此,您的问题可以这样重写:当内存地址是4的倍数时,当文档要求读取地址必须是512的倍数时,为什么读取工作呢?
答案是,文档没有对如果您违反规则会发生什么做出任何具体的保证。不管怎么说,这个电话还是会起作用的。无论如何,这一呼吁可能会奏效,但只会在偶数年的9月才起作用。无论如何,调用都可能起作用,但前提是内存地址为4的倍数。(这很可能取决于读取操作中涉及的特定硬件和设备驱动程序。仅仅因为它在你的机器上工作并不意味着它能在其他人的机器上工作。)
首先,将FILE_FLAG_NO_BUFFERING与FileStream一起使用可能不是一个好主意,因为我怀疑FileStream实际上是否保证将您给它的地址不经修改地传递给底层ReadFile调用。相反,使用P/Invoke直接调用底层API函数。您还可能需要以这种方式分配内存,因为我不知道.NET是否提供了以特定对齐方式分配内存的方法。
发布于 2016-04-28 14:04:18
只需直接用FILE_FLAG_NO_BUFFERING调用FILE_FLAG_NO_BUFFERING,然后在使用FileStream打开之前关闭它,以达到同样的效果。
https://stackoverflow.com/questions/12377914
复制相似问题