Blazor服务端应用中SignalR消息被多次接收是什么原因?
问题根因及解决方案:
组件生命周期管理不当,事件处理器重复注册
这是该场景下最高发的诱因:Blazor服务端应用中,若接收消息的组件每次渲染、激活、路由进入时都新建HubConnection实例并注册On事件,且组件销毁时没有主动释放连接、注销事件处理器,内存中就会残留多个存活的连接和事件处理器。你同事遇到的15次重复接收的情况完全符合该特征:每打开、刷新一次对应页面或组件,就多注册一个处理器,累计打开15次就会收到15次相同消息。
解决方法:让接收组件实现IAsyncDisposable接口,在销毁生命周期中主动注销事件、释放连接,示例代码:public async ValueTask DisposeAsync() { if (hubConnection != null) { // 移除Receive事件的所有注册处理器 hubConnection.Remove("Receive"); await hubConnection.DisposeAsync(); hubConnection = null; } }Hub连接的依赖注入生命周期配置错误
如果你通过DI容器注入HubConnection,错误将其注册为Transient(瞬态)或Scoped(作用域),会导致每个组件、每个用户请求都拿到全新的连接实例,所有存活的连接实例都会监听并响应同一条广播消息。
解决方法:如果全局只需要维护一个Hub连接,将其注册为单例即可:// Program.cs 注册代码 builder.Services.AddSingleton<HubConnection>(sp => { return new HubConnectionBuilder() .WithUrl("你的Hub服务地址") // 若开启自动重连注意不要在重连回调中重复注册事件 .WithAutomaticReconnect() .Build(); });自动重连逻辑导致重复注册事件
若你开启了WithAutomaticReconnect自动重连,且在重连成功的回调中重复执行了hubConnection.On事件注册逻辑,也会导致同一事件绑定多个相同处理器,触发多次回调。
解决方法:事件注册逻辑只在连接初始化时执行一次,不要放在重连回调中重复执行。服务端Hub处理逻辑异常
排除客户端问题后可排查服务端:检查Hub中Send方法的处理逻辑,是否存在循环调用、多次调用Clients.All.SendAsync或指定接收端发送方法的情况。
内容的提问来源于stack exchange,提问作者Avrohom Yisroel

