Blazor Server如何复用现有SignalR连接实现跨浏览器通知无需额外Hub
实现方案:复用Blazor Server原生连接实现全局广播通知
你不需要额外创建自定义SignalR Hub,只要利用Blazor Server内置的单例服务、Circuit通信机制即可实现全客户端实时刷新,全程复用原有SignalR连接,不会产生第二条连接。
具体实现步骤
- 第一步:创建全局单例通知服务
首先定义一个跨所有用户会话共享的通知服务,用于统一分发全局更新事件:
public class GlobalNotificationService { // 新增内容通知事件,可根据需求自定义参数结构 public event Action<string>? OnNewContentAdded; // 触发全局通知的方法 public void NotifyNewContentAdded(string content) { OnNewContentAdded?.Invoke(content); } }
在Program.cs中将服务注册为单例:builder.Services.AddSingleton<GlobalNotificationService>();
- 第二步:在表格页面组件中订阅通知
在包含数据表格的页面中注入通知服务,订阅更新事件,收到通知后自动刷新UI:
@inject GlobalNotificationService NotificationService @implements IAsyncDisposable <!-- 页面结构:文本框、提交按钮、数据表格 --> <input @bind="_inputContent" /> <button @onclick="HandleSubmit">提交</button> <table> @foreach(var item in _contentList) { <tr><td>@item</td></tr> } </table> @code { private List<string> _contentList = new(); private string _inputContent = string.Empty; protected override void OnInitialized() { // 组件初始化时订阅全局通知 NotificationService.OnNewContentAdded += HandleNewContent; // 此处可补充逻辑,初始化加载历史数据 } private void HandleNewContent(string newContent) { _contentList.Add(newContent); // 事件可能来自非UI线程,需用InvokeAsync保证UI更新线程安全 InvokeAsync(StateHasChanged); } private async Task HandleSubmit() { if(string.IsNullOrWhiteSpace(_inputContent)) return; // 此处可补充逻辑,将内容持久化到数据库/缓存 // 触发全局通知,所有打开页面的客户端都会收到更新 NotificationService.NotifyNewContentAdded(_inputContent); _inputContent = string.Empty; } // 组件销毁时取消订阅,避免内存泄漏 public async ValueTask DisposeAsync() { NotificationService.OnNewContentAdded -= HandleNewContent; } }
注意事项
- 多用户并发操作时,建议对共享的内容存储做线程安全处理,可使用
ConcurrentBag<T>等线程安全集合 - 如果需要区分不同业务场景的通知,可以在通知服务中定义多个不同的事件,或者在事件参数中增加业务类型标识
内容的提问来源于stack exchange,提问作者Bob5421
相关产品推荐
相关产品推荐

