.NET8 Blazor Hosted WASM流式响应UI实时更新异常排查
Blazor WASM流式响应未实时更新UI问题
环境背景
- 基于.NET8的Blazor Hosted WebAssembly应用,包含Client、Server、Shared三个项目
- Server端控制器通过
IAsyncEnumerable返回后端流式数据,但客户端需等待服务器完成所有迭代后才执行JSON反序列化并更新UI
Server端控制器代码
[HttpPost, Route("/api/chat/communicate_async")] public async IAsyncEnumerable<string> DoCommunicateAsync(ChatRequest chat) { IAsyncEnumerable<string> results = _IChat.DoCommunicateAsync(chat); await foreach (var result in results) { yield return result; } }
Client端两种流式接收尝试
方案一
CancellationToken cancellationToken = GetCancellationToken(); var requestContent = new StringContent(System.Text.Json.JsonSerializer.Serialize(chatRequest), Encoding.UTF8, "application/json"); using var requestMessage = new HttpRequestMessage(HttpMethod.Post, "api/chat/communicate_async") { Content = requestContent }; requestMessage.SetBrowserResponseStreamingEnabled(true); // 启用响应流式传输 using var response = await Http.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); using Stream stream = await response.Content.ReadAsStreamAsync(cancellationToken); var lines = System.Text.Json.JsonSerializer.DeserializeAsyncEnumerable<string>( stream, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, DefaultBufferSize = 128 }, cancellationToken); await foreach (string? line in lines) { chatResponse.response += line; StateHasChanged(); }
方案二
CancellationToken cancellationToken = GetCancellationToken(); chatResponse.response = string.Empty; var requestContent = new StringContent(System.Text.Json.JsonSerializer.Serialize(chatRequest), Encoding.UTF8, "application/json"); var requestMessage = new HttpRequestMessage(HttpMethod.Post, "api/chat/communicate_async") { Content = requestContent }; //requestMessage.Headers.Accept.Append(new MediaTypeWithQualityHeaderValue("application/stream+json")); requestMessage.SetBrowserResponseStreamingEnabled(true); // 启用响应流式传输 var response = await Http.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); IAsyncEnumerable<string?> results = response.Content.ReadFromJsonAsAsyncEnumerable<string>(); await foreach (string? result in results) { chatResponse.response += result; StateHasChanged(); }
已查阅多篇文章并尝试调整DefaultBufferSize等方案,问题仍未解决。
2024/05/28 更新
- 使用LLAMASharp本地大模型库的代码,虽通过
IAsyncEnumerable迭代,但客户端无法实现流式传输:
await foreach (string? result in session.ChatAsync(new ChatHistory.Message(AuthorRole.User, chat.prompt), inferenceParams, cancellationToken)) { if (result != null) { yield return result; } }
- 使用Azure.AI库的代码可正常在客户端流式传输:
await foreach (StreamingChatCompletionsUpdate chatUpdate in client.GetChatCompletionsStreaming(completionsOptions)) { string? result = chatUpdate.ContentUpdate; if (result != null) { yield return result; } }
求解决思路?
内容的提问来源于stack exchange,提问作者Stavros Koureas
相关产品推荐
相关产品推荐

