FileStream.Position se actualiza una vez completados ReadAsync o WriteAsync

FileStream.Position ahora se actualiza después de la finalización de ReadAsync o WriteAsync.

Descripción del cambio

En versiones anteriores de .NET en Windows, FileStream.Position se actualizaba después del inicio de la operación asincrónica de lectura o escritura. A partir de .NET 6, FileStream.Position se actualiza una vez terminadas esas operaciones.

El código siguiente muestra cómo difiere el valor de FileStream.Position entre las versiones anteriores de .NET y .NET 6.

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))
{
    Task[] writes = new Task[3];

    writes[0] = fs.WriteAsync(bytes, 0, bytes.Length);
    Console.WriteLine(fs.Position);  // 10000 in .NET 5, 0 in .NET 6

    writes[1] = fs.WriteAsync(bytes, 0, bytes.Length);
    Console.WriteLine(fs.Position);  // 20000 in .NET 5, 0 in .NET 6

    writes[2] = fs.WriteAsync(bytes, 0, bytes.Length);
    Console.WriteLine(fs.Position);  // 30000 in .NET 5, 0 in .NET 6

    await Task.WhenAll(writes);
    Console.WriteLine(fs.Position);  // 30000 in all versions
}

Versión introducida

.NET 6

Motivo del cambio

FileStream nunca ha sido seguro para subprocesos, pero hasta .NET 6, .NET ha intentado admitir varias llamadas simultáneas a sus métodos asincrónicos (ReadAsync y WriteAsync) en Windows.

Este cambio se ha incorporado para permitir una E/S de archivos 100 % asincrónica con FileStream y para corregir los siguientes problemas:

Ahora, cuando el almacenamiento en búfer está habilitado (es decir, el argumento bufferSize que se pasa al constructor de FileStream es mayor que 1), se serializan todas las operaciones ReadAsync y WriteAsync.

  • Modifique cualquier código que dependa del establecimiento de la posición antes de que se completen las operaciones.

  • Para habilitar el comportamiento de .NET 5 en .NET 6, especifique un modificador AppContext o una variable de entorno. Al establecer el modificador en true, opta por no recibir todas las mejoras de rendimiento realizadas en FileStream en .NET 6.

    {
        "configProperties": {
            "System.IO.UseNet5CompatFileStream": true
        }
    }
    
    set DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM=1
    

    Nota

    Este modificador solo está disponible en .NET 6. Se quitó en .NET 7.

API afectadas