.NET Core 6异步流式API消费异常:结果批量返回而非实时输出
实时流式API与消费应用的批量返回问题
我正在构建一个可实时返回就绪结果的API,目标如下:
- 实现一个可在结果就绪时立即输出的API端点
- 构建一个消费应用,可在结果就绪时立即处理数据
我的API调用另一个服务的代码如下:
[HttpGet] [Route("stream")] public async IAsyncEnumerable<ReturnModel> GetStream() { // 单独声明请求消息变量,因为后续Post请求也要用 var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(the_url_that_allowed_streaming_of_data) }; var client = new HttpClient(); client.DefaultRequestHeaders.Add("Accept", "application/json"); // Post请求需要这个头 var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); using var reader = new StreamReader(stream); while (!reader.EndOfStream) { var message = await reader.ReadLineAsync(); Console.WriteLine(message); // 用于检查是否能快速获取数据 // 在这里处理message yield return new ReturnModel { ... }; } }
在浏览器访问该URL(stream)时,响应是批量输出的(多个yield结果一起返回而非逐个返回)。我在控制台应用中使用以下代码消费该API,也出现了同样的批量返回问题:
static async Task ConsumeStream(string url) { var client = new HttpClient(); var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(url), }; var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); IAsyncEnumerable<ReturnModel> items = System.Text.Json.JsonSerializer .DeserializeAsyncEnumerable<ReturnModel>( stream, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, DefaultBufferSize = 10 // 不管设什么值,结果都一样 }); var lineCtr = 0; await foreach (var item in items) { lineCtr++; Console.WriteLine($"Line: {lineCtr} ---- Time: {DateTime.Now.ToLongTimeString()} ---- Content: {item.Content}"); // 不会立即输出 } }
我尝试了另一种方法,但情况更糟,似乎要等待所有数据加载完成后才会处理并输出到控制台:
// 所有Console.WriteLine会一次性显示在窗口中 static async Task ConsumeStreamV2(string url) { var client = new HttpClient(); var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(url), }; var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); var stream = await response.Content.ReadAsStreamAsync(); using var reader = new StreamReader(stream); while (!reader.EndOfStream) { var message = await reader.ReadLineAsync(); Console.WriteLine($"Time: {DateTime.Now.ToLongTimeString()} ---- Content: {message}"); } }
我遗漏了什么?
内容的提问来源于stack exchange,提问作者von v.
相关产品推荐
相关产品推荐

