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:
- FileStream Win32 genererà una ricerca per ogni chiamata ReadAsync
- Le chiamate useAsync WriteAsync FileStream.Windows bloccano le API
Con questa modifica, le operazioni ReadAsync sono fino a due volte più veloci e le operazioni WriteAsync sono fino a cinque volte più veloci.
Azione consigliata
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 sutrue
, si rifiutano esplicitamente tutti i miglioramenti delle prestazioni apportati aFileStream
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.