FileStream ne synchronise plus le décalage de fichier avec le système d’exploitation

Pour améliorer le niveau de performance, FileStream ne synchronise plus le décalage de fichier avec le système d’exploitation.

Description de la modification

Dans les versions précédentes de .NET, FileStream synchronise le décalage de fichier avec le système d’exploitation Windows lorsqu’il lit ou écrit dans un fichier. Il synchronise le décalage en appelant SetFilePointer, qui est un appel système coûteux. À partir de .NET 6, FileStream ne synchronise plus le décalage de fichier et conserve simplement le décalage en mémoire. FileStream.Position retourne toujours le décalage actuel, mais si vous obtenez le descripteur de fichier à partir de FileStream.SafeFileHandle et interrogez le système d’exploitation pour le décalage de fichier actuel à l’aide d’un appel système, la valeur de décalage sera 0.

Le code suivant montre comment le décalage de fichier diffère entre les versions .NET précédentes et .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 introduite

.NET 6

Raison du changement

Ce changement a été introduit pour améliorer le niveau de performance des lectures et écritures asynchrones et pour résoudre les problèmes suivants :

Avec ce changement, les opérations ReadAsync sont jusqu’à deux fois plus rapides et les opérations WriteAsync sont jusqu’à cinq fois plus rapides.

  • Modifiez tout code qui s’appuyait sur le décalage en cours de synchronisation.

  • Pour activer le comportement .NET 5 dans .NET 6, spécifiez un commutateur AppContext ou une variable d’environnement. En définissant le commutateur sur true, vous désactivez toutes les améliorations du niveau de performance apportées à FileStream dans .NET 6.

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

    Notes

    Ce commutateur est disponible uniquement dans .NET 6. Il a été supprimé dans .NET 7.

API affectées

Aucun.

Voir aussi