Condividi tramite


FileStream non sincronizza più l'offset del file con il sistema operativo

Per migliorare le prestazioni, FileStream non sincronizza più l'offset del file con il sistema operativo.

Descrizione delle modifiche

Nelle versioni precedenti di .NET, FileStream sincronizza l'offset di file con il sistema operativo Windows quando legge o scrive in un file. Sincronizza l'offset chiamando SetFilePointer, che è una chiamata di sistema onerosa. A partire da .NET 6, FileStream non sincronizza più l'offset del file e mantiene invece l'offset in memoria. FileStream.Position restituisce sempre l'offset corrente, ma se si ottiene l'handle di file da FileStream.SafeFileHandle e si esegue una query sul sistema operativo per l'offset del file corrente usando una chiamata di sistema, il valore di offset sarà 0.

Il codice seguente illustra le differenze per l'offset dei file tra le versioni precedenti di .NET e .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
    }
}

Versione di introduzione

.NET 6

Motivo della modifica

Questa modifica è stata introdotta per migliorare le prestazioni delle letture e scritture asincrone e per risolvere i problemi seguenti:

Con questa modifica, le operazioni ReadAsync sono fino a due volte più veloci e le operazioni WriteAsync sono fino a cinque volte più veloci.

  • Modificare qualsiasi codice che dipende dalla sincronizzazione dell'offset.

  • Per abilitare il comportamento di .NET 5 in .NET 6, specificare un'opzione AppContext o una variabile di ambiente. Impostando l'opzione su true, si rifiutano esplicitamente tutti i miglioramenti delle prestazioni apportati a FileStream in .NET 6.

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

    Nota

    Questa opzione è disponibile solo in .NET 6. È stata rimossa in .NET 7.

API interessate

Nessuno.

Vedi anche