Skip to content

StreamReader.ReadLineAsync() does not return before its internal buffer is full #79238

Closed
@oleneveu

Description

@oleneveu

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

That bug report is about a regression between Blazor 6.0.11 and Blazor 7.0.0

Conditions:

  • An API endpoint on the server produces a stream of data (text) slowly: A single line of text is added to the response every second.
  • A method on the client side (Blazor WASM) reads that stream of data line-by-line using StreamReader.ReadLineAsync().
  • All prerequisites to enable response streaming are met (HttpRequestMessage.SetBrowserResponseStreamingEnabled(true), HttpCompletionOption.ResponseHeadersRead)

When using Blazor 6.0.11, each time a line-break is received in the stream of data, the method StreamReader.ReadLineAsync() returns the text that was preceding that line-break.

With Blazor 7.0.0, the method StreamReader.ReadLineAsync() will not return before the StreamReader's internal buffer has been entirely filled, which means that several lines of text can be received before StreamReader.ReadLineAsync() returns them all consecutively.

When reading the data directly from the response stream, that behavior disappear and all the data is available as soon as it is received. That seems to suggest that the issue is only due to the StreamReader.

However, that issue cannot be reproduced when the client code is executed from a console application: The behavior is then exactly the same when using .Net 6 and .Net 7: StreamReader.ReadLineAsync() returns on every line break without waiting for the buffer to be full.

Expected Behavior

The StreamReader should behave the same way when using Blazor 6.0.11 and Blazor 7.0.0: StreamReader.ReadLineAsync() should return as soon as a line-break is available from the input stream.

Steps To Reproduce

A minimal project to reproduce the issue is available here:
https://github.com/oleneveu/BlazorStreamReaderIssue

It is based on the template from Visual Studio. The code that reproduces the issue is located here:

  • Server side: DataStreamingController.cs
  • Client side: StreamData.razor

The project currently targets Blazor 7.0.0.
To compare the behavior with Blazor 6.0.11, all projects files must be modified to target .Net 6 and all packages references must be changed from 7.0.0 to 6.0.11. No other changes should be required.

Steps to reproduce:

  • Start the project
  • Open the 'Stream data' menu from the Blazor application
  • Blazor 7: The text 'Streamed data: Waiting for server data...' is displayed for about 17 seconds before being updated. It is then updated every 17 seconds or so.
  • Blazor 6: The text 'Streamed data: Waiting for server data...' is updated immediately and then every 1 second or so.

Note: Each line of text sent by the server contains 7 bytes (5 digits + CR/LF) . Within 17 seconds, 18 lines or 126 bytes are sent. When the 19th line is sent, the total size exceeds the buffer size of the StreamReader (configured to 128 bytes in the sample project).
When changing the buffer size of the StreamReader, the delay before the first update changes accordingly.

Update: I have added a console application to the solution ('ConsoleStreaming') to perform the same test that is made from the Blazor component and highlight the difference in behavior. To run this test:

  • Start the server (BlazorStreaming.Server)
  • Start the console app (ConsoleStreaming)
    When a line of text is added to the response from the 'DataStreamingController.Get()' endpoint, that line is immediately displayed in the console.

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions