Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Para mejorar el rendimiento, FileStream ya no sincroniza el offset de archivo con el sistema operativo.
Descripción del cambio
En versiones anteriores de .NET, FileStream sincroniza el desplazamiento de archivos con el sistema operativo Windows cuando lee o escribe en un archivo. Sincroniza el desplazamiento mediante una llamada a SetFilePointer, que es una llamada del sistema costosa. A partir de .NET 6, FileStream ya no sincroniza el desplazamiento del archivo y, en su lugar, simplemente mantiene el desplazamiento en la memoria. FileStream.Position siempre devuelve el desplazamiento actual, pero si obtiene el identificador de archivo de FileStream.SafeFileHandle y consulta al sistema operativo para obtener el desplazamiento de archivo actual mediante una llamada del sistema, el valor de desplazamiento será 0.
El código siguiente muestra cómo difiere el desplazamiento de archivo entre las versiones anteriores de .NET y .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
}
}
Versión introducida
.NET 6
Motivo del cambio
Este cambio se introdujo para mejorar el rendimiento de las lecturas y escrituras asincrónicas y solucionar los siguientes problemas:
- Win32 FileStream realizará una búsqueda cada vez que se llame a ReadAsync
- Filestream.Windows useAsync WriteAsync llama a API de bloqueo
Con este cambio, ReadAsync las operaciones son hasta dos veces más rápidas y WriteAsync las operaciones son hasta cinco veces más rápidas.
Acción recomendada
Modifique cualquier código que dependa de la sincronización del desplazamiento.
Para habilitar el comportamiento de .NET 5 en .NET 6, debe especificar un
AppContext
conmutador o una variable de entorno. Al configurar el interruptor entrue
, opta por no participar en todas las mejoras de rendimiento realizadas aFileStream
en .NET 6.{ "configProperties": { "System.IO.UseNet5CompatFileStream": true } }
set DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM=1
Nota:
Este conmutador solo está disponible en .NET 6. Se eliminó en .NET 7.
Las APIs afectadas
Ninguno.