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

.NET 8 Blazor Server中SignalR接收Rebus消息后视图不更新

.NET 8 Blazor Server中Rebus+SignalR推送后视图不更新的解决方案

问题背景

将Blazor Server应用从.NET 6升级至.NET 8后,通过RebusQueue接收消息并经SignalR推送时,已确认数据(如forecasts数组)已更新,但页面视图未同步渲染变化。

核心原因

.NET 8的Blazor Server在InteractiveServer渲染模式下,组件的状态更新依赖Blazor同步上下文(Dispatcher线程)。而SignalR的回调默认运行在后台线程,直接调用StateHasChanged()无法触发视图渲染;同时数组类型的状态变更无法自动触发组件更新机制。

解决方案

1. 确保在Blazor同步上下文执行状态更新

SignalR回调线程不属于Blazor组件的同步上下文,需通过InvokeAsync()将操作调度到正确线程:

修改NotificationListener组件的SignalR回调:

hubConnection.On<string>("sendMessage", async (message) =>
{
    // 用InvokeAsync切换到Blazor组件上下文
    await InvokeAsync(async () =>
    {
        await OnMessageReceivedCallback.InvokeAsync(message);
        StateHasChanged();
    });
});

修改Weather.razor的HandleNotification方法:

private async Task HandleNotification(string message)
{
    await InvokeAsync(() =>
    {
        var list = forecasts.ToList();
        int.TryParse(message.Substring(message.Length - 1), out var counter);
        list.Add(new WeatherForecast() 
        { 
            Date = DateOnly.FromDateTime(DateTime.Now), 
            Summary = message, 
            TemperatureC = counter 
        });
        forecasts = list.ToArray();
        StateHasChanged();
    });
}

2. 优化状态管理:使用可观察集合替代数组

将forecasts从数组改为ObservableCollection<WeatherForecast>,集合变化时会自动触发视图更新,无需手动调用StateHasChanged():

Weather.razor中修改状态定义:

private ObservableCollection<WeatherForecast> forecasts = new ObservableCollection<WeatherForecast>();

private async Task HandleNotification(string message)
{
    await InvokeAsync(() =>
    {
        int.TryParse(message.Substring(message.Length - 1), out var counter);
        forecasts.Add(new WeatherForecast() 
        { 
            Date = DateOnly.FromDateTime(DateTime.Now), 
            Summary = message, 
            TemperatureC = counter 
        });
    });
}

3. 完善Hub连接生命周期管理

在InteractiveServer模式下,组件与连接生命周期绑定,需在组件销毁时关闭Hub连接避免资源泄漏:

NotificationListener组件中添加Dispose逻辑:

public override async Task DisposeAsync()
{
    if (hubConnection != null)
    {
        await hubConnection.StopAsync();
        await hubConnection.DisposeAsync();
    }
    await base.DisposeAsync();
}

4. 验证Rebus与SignalR的配置一致性

确认Rebus的SignalR命令映射与Hub端点配置匹配:

  • 确保MapSignalRCommands<NotificationsHub>(queueName)中的queueName与接收消息的队列一致
  • 检查app.UseEndpoints中Hub的映射路径/chatapi与客户端连接路径一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:56:01