|
| 1 | +--- |
| 2 | +title: ".NET 6 breaking change: FileStream.Position updated after ReadAsync or WriteAsync completion" |
| 3 | +description: Learn about the .NET 6 breaking change in core .NET libraries where FileStream.Position is updated after ReadAsync or WriteAsync completion. |
| 4 | +ms.date: 05/05/2021 |
| 5 | +--- |
| 6 | +# FileStream.Position updates after ReadAsync or WriteAsync completes |
| 7 | + |
| 8 | +<xref:System.IO.FileStream.Position?displayProperty=nameWithType> is now updated after <xref:System.IO.FileStream.ReadAsync%2A> or <xref:System.IO.FileStream.WriteAsync%2A> completes. |
| 9 | + |
| 10 | +## Change description |
| 11 | + |
| 12 | +In previous .NET versions on Windows, <xref:System.IO.FileStream.Position?displayProperty=nameWithType> is updated after the asynchronous read or write operation starts. Starting in .NET 6, <xref:System.IO.FileStream.Position?displayProperty=nameWithType> is updated after those operations complete. |
| 13 | + |
| 14 | +The following code shows how the value of <xref:System.IO.FileStream.Position?displayProperty=nameWithType> differs between previous .NET versions and .NET 6. |
| 15 | + |
| 16 | +```csharp |
| 17 | +byte[] bytes = new byte[10_000]; |
| 18 | +string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); |
| 19 | + |
| 20 | +using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize: 4096, useAsync: true)) |
| 21 | +{ |
| 22 | + Task[] writes = new Task[3]; |
| 23 | + |
| 24 | + writes[0] = fs.WriteAsync(bytes, 0, bytes.Length); |
| 25 | + Console.WriteLine(fs.Position); // 10000 in .NET 5, 0 in .NET 6 |
| 26 | +
|
| 27 | + writes[1] = fs.WriteAsync(bytes, 0, bytes.Length); |
| 28 | + Console.WriteLine(fs.Position); // 20000 in .NET 5, 0 in .NET 6 |
| 29 | +
|
| 30 | + writes[2] = fs.WriteAsync(bytes, 0, bytes.Length); |
| 31 | + Console.WriteLine(fs.Position); // 30000 in .NET 5, 0 in .NET 6 |
| 32 | +
|
| 33 | + await Task.WhenAll(writes); |
| 34 | + Console.WriteLine(fs.Position); // 30000 in all versions |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +## Version introduced |
| 39 | + |
| 40 | +6.0 Preview 4 |
| 41 | + |
| 42 | +## Reason for change |
| 43 | + |
| 44 | +<xref:System.IO.FileStream> has never been thread-safe, but until .NET 6, .NET has tried to support multiple concurrent calls to its asynchronous methods (<xref:System.IO.FileStream.ReadAsync%2A> and <xref:System.IO.FileStream.WriteAsync%2A>) on Windows. |
| 45 | + |
| 46 | +This change was introduced to allow for 100% asynchronous file I/O with <xref:System.IO.FileStream> and to fix the following issues: |
| 47 | + |
| 48 | +- [FileStream.FlushAsync ends up doing synchronous writes](https://github.com/dotnet/runtime/issue/27643) |
| 49 | +- [Win32 FileStream turns async reads into sync reads](https://github.com/dotnet/runtime/issue/16341) |
| 50 | + |
| 51 | +Now, when buffering is enabled (that is, the `bufferSize` argument that's passed to the [FileStream constructor](xref:System.IO.FileStream.%23ctor%2A) is greater than 1), every <xref:System.IO.FileStream.ReadAsync%2A> and <xref:System.IO.FileStream.WriteAsync%2A> operation is serialized. |
| 52 | + |
| 53 | +## Recommended action |
| 54 | + |
| 55 | +- Modify any code that relied on the position being set before operations completed. |
| 56 | + |
| 57 | +- To enable the .NET 5 behavior in .NET 6, specify an `AppContext` switch or an environment variable. By setting the switch to `true`, you opt out of all performance improvements made to `FileStream` in .NET 6. |
| 58 | + |
| 59 | + ```xml |
| 60 | + { |
| 61 | + "configProperties": { |
| 62 | + "System.IO.UseNet5CompatFileStream": true |
| 63 | + } |
| 64 | + } |
| 65 | + ``` |
| 66 | + |
| 67 | + ```cmd |
| 68 | + set DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM=1 |
| 69 | + ``` |
| 70 | + |
| 71 | +## Affected APIs |
| 72 | + |
| 73 | +- <xref:System.IO.FileStream.Position?displayProperty=fullName> |
| 74 | + |
| 75 | +<!-- |
| 76 | +
|
| 77 | +### Category |
| 78 | +
|
| 79 | +- Core .NET libraries |
| 80 | +
|
| 81 | +### Affected APIs |
| 82 | +
|
| 83 | +- `P:System.IO.FileStream.Position` |
| 84 | +
|
| 85 | +--> |
0 commit comments