为了提高性能,FileStream 不再将文件偏移量与操作系统同步。
更改描述
在以前的 .NET 版本中,读取或写入文件时,FileStream 会将文件偏移量与 Windows 操作系统(OS)同步。 它通过调用 SetFilePointer 来同步偏移量,这是一个昂贵的系统调用。 从 .NET 6 开始, FileStream 不再同步文件偏移量,而是只保留内存中的偏移量。 FileStream.Position 始终返回当前偏移量,但如果使用系统调用从 FileStream.SafeFileHandle OS 获取文件句柄并查询当前文件偏移量,则偏移值为 0。
以下代码展示了文件偏移量在 .NET 早期版本与.NET 6 之间的差异。
[DllImport("kernel32.dll")]
private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, out long lpNewFilePointer, uint dwMoveMethod);
byte[] bytes = new byte[10_000];
string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize: 4096, useAsync: true))
{
SafeFileHandle handle = fs.SafeFileHandle;
await fs.WriteAsync(bytes, 0, bytes.Length);
Console.WriteLine(fs.Position); // 10000 in all versions
if (SetFilePointerEx(handle, 0, out long currentOffset, 1 /* get current offset */))
{
Console.WriteLine(currentOffset); // 10000 in .NET 5, 0 in .NET 6
}
}
已引入的版本
.NET 6
更改原因
引入了此更改以提高异步读取和写入的性能,并解决了以下问题:
通过此更改,ReadAsync 操作速度高达两倍,WriteAsync 操作速度高达五倍。
建议的措施
修改任何依赖于要同步的偏移量的代码。
若要在 .NET 6 中启用 .NET 5 行为,请指定
AppContext
开关或环境变量。 通过将开关设置为true
,可以选择退出 .NET 6 中对FileStream
进行的所有性能改进。{ "configProperties": { "System.IO.UseNet5CompatFileStream": true } }
set DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM=1
注释
此开关仅在 .NET 6 中可用。 它在 .NET 7 中已移除。
受影响的 API
没有。