Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
To improve performance, FileStream no longer synchronizes the file offset with the operating system.
Change description
In previous .NET versions, FileStream synchronizes the file offset with the Windows operating system (OS) when it reads or writes to a file. It synchronizes the offset by calling SetFilePointer, which is an expensive system call. Starting in .NET 6, FileStream no longer synchronizes the file offset, and instead just keeps the offset in memory. FileStream.Position always returns the current offset, but if you obtain the file handle from FileStream.SafeFileHandle and query the OS for the current file offset using a system call, the offset value will be 0.
The following code shows how the file offset differs between previous .NET versions and .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
}
}
Version introduced
.NET 6
Reason for change
This change was introduced to improve the performance of asynchronous reads and writes and to address the following issues:
- Win32 FileStream will issue a seek on every ReadAsync call
- FileStream.Windows useAsync WriteAsync calls blocking APIs
With this change, ReadAsync operations are up to two times faster, and WriteAsync operations are up to five times faster.
Recommended action
Modify any code that relied on the offset being synchronized.
To enable the .NET 5 behavior in .NET 6, specify an
AppContext
switch or an environment variable. By setting the switch totrue
, you opt out of all performance improvements made toFileStream
in .NET 6.{ "configProperties": { "System.IO.UseNet5CompatFileStream": true } }
set DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM=1
Note
This switch is only available in .NET 6. It was removed in .NET 7.
Affected APIs
None.