Filestream 不再與 OS 同步檔案位移
為了改善效能,FileStream 不再與作業系統同步檔案位移。
變更描述
在舊版 .NET 中,當 FileStream 讀取或寫入檔案時,會同步檔案位移與 Windows 作業系統 (OS)。 其藉由呼叫 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
無。