共用方式為


FileStream 不再與 OS 同步處理檔案位移

若要改善效能,FileStream 不再與作業系統同步檔案位移。

變更描述

在先前版本的 .NET 中,FileStream 會在檔案讀取或寫入檔案時,將檔案位移與 Windows 作業系統同步。 它會藉由呼叫 SetFilePointer 來同步位移,這是耗費大量資源的系統呼叫。 從 .NET 6 開始, FileStream 不再同步處理檔案位移,而只會將位移保留在記憶體中。 FileStream.Position 一律會傳回目前的位移,但如果您從 FileStream.SafeFileHandle 取得檔句柄,並使用系統呼叫查詢 OS 的目前檔案位移,則位移值會是 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 6 中啟用 .NET 5 行為,請指定 AppContext 參數或環境變數。 將開關設定為 true,您可以退出 .NET 6 中對 FileStream 進行的所有效能改進。

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

    備註

    此參數僅適用於 .NET 6。 它已在 .NET 7 中移除

受影響的 API

沒有。

另請參閱