Поделиться через


FileStream больше не синхронизирует смещение файлов с ОС

Чтобы повысить производительность, FileStream больше не синхронизирует смещение файла с операционной системой.

Описание изменения

В предыдущих версиях FileStream .NET синхронизирует смещение файла с операционной системой Windows при чтении или записи в файл. Он синхронизирует смещение путем вызова SetFilePointer, который является дорогостоящим системным вызовом. Начиная с .NET 6, FileStream больше не синхронизирует смещение файла и вместо этого просто сохраняет смещение в памяти. FileStream.Position всегда возвращает текущее смещение, но если вы получаете дескриптор файла из FileStream.SafeFileHandle и запрашиваете ОС о текущем смещении файла с помощью системного вызова, значение смещения будет равно 0.

В следующем коде показано, чем отличается смещение файла в предыдущих версиях .NET по сравнению с .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
    }
}

Представленная версия

.NET 6

Причина изменения

Это изменение было введено для повышения производительности асинхронных операций чтения и записи и устранения следующих проблем:

С этим изменением ReadAsync операции выполняются до двух раз быстрее, а WriteAsync операции — до пяти раз быстрее.

  • Измените любой код, зависящий от синхронизированного смещения.

  • Чтобы включить поведение .NET 5 в .NET 6, укажите AppContext переключатель или переменную среды. Установив переключатель true, вы отказываетесь от всех улучшений производительности, осуществленных FileStream в .NET 6.

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

    Замечание

    Этот переключатель доступен только в .NET 6. Он был удален в .NET 7.

Затронутые API

Нет.

См. также