c# - 如何在 c# 中禁用磁盘缓存使用 FILE_FLAG_NO_BUFFERING 调用 win32 CreateFile api

标签 c# pinvoke filestream createfile

大家,我每秒有很多文件写入磁盘,我想禁用磁盘缓存以提高性能,我谷歌搜索找到解决方案:win32 CreateFile 方法与 FILE_FLAG_NO_BUFFERING 和 How to empty/flush Windows READ disk cache in C#? .

我写了一些代码来测试是否可以工作:

const int FILE_FLAG_NO_BUFFERING = unchecked((int)0x20000000);

[DllImport("KERNEL32", SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
static extern SafeFileHandle CreateFile(
      String fileName,
      int desiredAccess,
      System.IO.FileShare shareMode,
      IntPtr              securityAttrs,
      System.IO.FileMode  creationDisposition,
      int                 flagsAndAttributes,
      IntPtr              templateFile);

static void Main(string[] args)
{
    var handler = CreateFile(@"d:\temp.bin", (int)FileAccess.Write, FileShare.None,IntPtr.Zero, FileMode.Create, FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
    var stream = new FileStream(handler, FileAccess.Write, BlockSize);//BlockSize=4096
    byte[] array = Encoding.UTF8.GetBytes("hello,world");
    stream.Write(array, 0, array.Length);
    stream.Close();
}

运行此程序时,应用程序出现异常:IO 操作将不起作用。很可能文件会变得太长或句柄未打开以支持同步 IO 操作

后来找到这篇文章When you create an object with constraints, you have to make sure everybody who uses the object understands those constraints ,但我不能完全理解,所以我改变了我的代码来测试:

var stream = new FileStream(handler, FileAccess.Write, 4096);
byte[] ioBuffer = new byte[4096];
byte[] array = Encoding.UTF8.GetBytes("hello,world");
Array.Copy(array, ioBuffer, array.Length);
stream.Write(ioBuffer, 0, ioBuffer.Length);
stream.Close();

它运行正常,但我只想要“hello,world”字节而不是全部。我尝试将 block 大小更改为 1 或其他整数(不是 512 的倍数)得到同样的错误。我也尝试 win32 WriteFile api 也得到同样的错误。有人可以帮我吗?

最佳答案

无缓冲模式下的 CreateFile() 函数强加 strict requirements关于可以做什么和不可以做什么。拥有一定大小的缓冲区(设备扇区大小的倍数)就是其中之一。

现在,只有在代码中使用缓冲,才能以这种方式改进文件写入。如果你想在没有缓冲的情况下写入 10 个字节,那么无缓冲模式将无济于事。

关于c# - 如何在 c# 中禁用磁盘缓存使用 FILE_FLAG_NO_BUFFERING 调用 win32 CreateFile api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8692635/

相关文章:

c# - 如何将部分预缓存的MemoryStream与FileStream结合起来?

c# - FileStream.Write 不写入文件

c# - 带有LoadAsync()的Query()不会返回实体,尽管它应该

c# - 我怎么知道一个类型是否可以使用 Json.NET 转换?

c# - 删除对 ASP.NET Core ApiController 的请求不起作用

c# - 非聚合根可以保存另一个非聚合根的引用吗?

c# - 来自 user32.dll 的 DragDetect (IntPtr, Point) 在单声道中是否等效?

c# - 当外部应用程序的窗口移动时移动窗口

c# - 如何通过 Visual Studio COM 包装器(或其他方式)在 C# 中使用 C++ 属性 union

java - 无法在 html 请求中下载大文件