Udostępnij za pośrednictwem


PlikStream nie synchronizuje już przesunięcia pliku z systemem operacyjnym

Aby zwiększyć wydajność, FileStream nie synchronizuje już przesunięcia pliku z systemem operacyjnym.

Opis zmiany

W poprzednich wersjach FileStream platformy .NET synchronizuje przesunięcie pliku z systemem operacyjnym Windows podczas odczytu lub zapisu w pliku. Synchronizuje przesunięcie, wywołując metodę SetFilePointer, która jest kosztownym wywołaniem systemowym. Począwszy od platformy .NET 6, FileStream nie synchronizuje już przesunięcia pliku, a zamiast tego po prostu zachowuje przesunięcie w pamięci. FileStream.Position zawsze zwraca bieżące przesunięcie, ale jeśli uzyskasz dojście do pliku i FileStream.SafeFileHandle wykonasz zapytanie dotyczące systemu operacyjnego dla bieżącego przesunięcia pliku przy użyciu wywołania systemowego, wartość przesunięcia będzie wynosić 0.

Poniższy kod pokazuje, jak przesunięcie pliku różni się między poprzednimi wersjami platformy .NET i platformą .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
    }
}

Wprowadzona wersja

.NET 6

Przyczyna wprowadzenia zmiany

Ta zmiana została wprowadzona w celu zwiększenia wydajności asynchronicznych odczytów i zapisów oraz rozwiązania następujących problemów:

Dzięki tej zmianie ReadAsync operacje są do dwóch razy szybsze, a WriteAsync operacje są maksymalnie pięć razy szybsze.

  • Zmodyfikuj dowolny kod, który polegał na synchronizowaniu przesunięcia.

  • Aby włączyć zachowanie platformy .NET 5 na platformie .NET 6, określ AppContext przełącznik lub zmienną środowiskową. Ustawiając przełącznik na true, zrezygnujesz ze wszystkich ulepszeń wydajności w FileStream programie .NET 6.

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

    Uwaga

    Ten przełącznik jest dostępny tylko na platformie .NET 6. Został on usunięty na platformie .NET 7.

Dotyczy interfejsów API

Brak.

Zobacz też