You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 Blazor WASM基于IAsyncEnumerable的HTTP文本流无缓冲处理问题

根因分析
  1. Blazor WebAssembly的HttpClient底层基于浏览器Fetch API实现,默认会对响应体做全量缓冲,就算设置了HttpCompletionOption.ResponseHeadersRead也不会生效。
  2. System.Text.Json默认的异步反序列化缓冲区大小为16KB,会攒够数据才开始解析,小体积的流式响应会被延迟处理。
修复步骤

第一步:服务端补充配置(避免服务端侧缓冲)

先确保服务端本身没有对响应做缓冲,修改API代码如下:

using Microsoft.AspNetCore.Http.Features;

[HttpGet("lines")]
public async IAsyncEnumerable<string> GetLines()
{
    // 禁用服务端响应缓冲
    Response.Headers.CacheControl = "no-cache";
    Response.ContentType = "application/json; charset=utf-8";
    HttpContext.Features.Get<IHttpResponseBodyFeature>()?.DisableBuffering();

    for (var i = 0; i < 10; ++i)
    {
        yield return "test";
        await Task.Delay(1000);
    }
}

第二步:客户端代码修改

首先引入Blazor WASM专属的HTTP扩展命名空间,开启浏览器侧的流式响应支持,同时缩小JSON反序列化的缓冲区:

using Microsoft.AspNetCore.Components.WebAssembly.Http;
using System.Text.Json;

public async IAsyncEnumerable<string?> GetLines()
{
    var request = new HttpRequestMessage(HttpMethod.Get, $"{apiRoot}/lines");
    // 关键:开启浏览器Fetch API的流式响应支持,禁用缓冲
    request.SetBrowserResponseStreamingEnabled(true);

    var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    if (response.IsSuccessStatusCode)
    {
        var responseStream = await response.Content.ReadAsStreamAsync();
        // 配置JSON序列化器使用最小缓冲区
        var jsonOptions = new JsonSerializerOptions
        {
            DefaultBufferSize = 64,
            PropertyNameCaseInsensitive = true
        };

        await foreach (var line in JsonSerializer.DeserializeAsyncEnumerable<string>(responseStream, jsonOptions))
        {
            yield return line;
        }
    }
    else
    {
        Log.Error($"Server response code: {response.StatusCode}");
        yield return null;
    }
}
可选优化(纯文本场景)

如果你的业务场景只需要传输纯文本换行分隔内容,不需要JSON序列化,可以直接用StreamReader逐行读取,延迟更低:

// 替换JSON反序列化部分即可
using var reader = new StreamReader(responseStream);
while (!reader.EndOfStream)
{
    var line = await reader.ReadLineAsync();
    yield return line;
}

内容的提问来源于stack exchange,提问作者Frank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 08:54:09