ReadAsync 또는 WriteAsync 완료 후 FileStream.Position 업데이트

FileStream.Position은 이제 ReadAsync 또는 WriteAsync가 완료된 후 업데이트됩니다.

변경 내용 설명

Windows의 이전 .NET 버전에서는 비동기 읽기 또는 쓰기 작업이 시작된 후 FileStream.Position이 업데이트되었습니다. .NET 6부터는 이러한 작업이 완료된 후 FileStream.Position이 업데이트됩니다.

다음 코드는 FileStream.Position의 값이 이전 .NET 버전과 .NET 6 간에 어떻게 다른지를 보여 줍니다.

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))
{
    Task[] writes = new Task[3];

    writes[0] = fs.WriteAsync(bytes, 0, bytes.Length);
    Console.WriteLine(fs.Position);  // 10000 in .NET 5, 0 in .NET 6

    writes[1] = fs.WriteAsync(bytes, 0, bytes.Length);
    Console.WriteLine(fs.Position);  // 20000 in .NET 5, 0 in .NET 6

    writes[2] = fs.WriteAsync(bytes, 0, bytes.Length);
    Console.WriteLine(fs.Position);  // 30000 in .NET 5, 0 in .NET 6

    await Task.WhenAll(writes);
    Console.WriteLine(fs.Position);  // 30000 in all versions
}

도입된 버전

.NET 6

변경 이유

FileStream은 스레드로부터 안전하지 않았지만 .NET 6까지 .NET은 Windows에서 비동기 메서드(ReadAsyncWriteAsync)에 대한 여러 동시 호출을 지원하려고 했습니다.

FileStream을 통한 100% 비동기 파일 I/O를 허용하고 다음 문제를 수정하기 위해 변경이 도입되었습니다.

이제 버퍼링이 사용되면(즉, FileStream 생성자에 전달된 bufferSize 인수가 1보다 큼) 모든 ReadAsyncWriteAsync 작업이 직렬화됩니다.

  • 작업이 완료되기 전에 설정되는 위치에 의존하는 코드를 수정합니다.

  • .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