Blazor Server生产设备管理应用页面数据刷新实现方案咨询
Blazor Server 动态数据刷新实现方案
以下是两种需求对应的可落地实现思路及代码示例:
方案1:定时轮询刷新(实现成本最低,适合非强实时场景)
该方案无需额外依赖,仅需在页面内置定时任务拉取数据即可,10秒轮询的性能开销可以忽略不计。
实现代码
@implements IAsyncDisposable @inject IProductionDataService ProductionDataService <p>当前完工工件数量:@FinishedCount</p> @code { private int FinishedCount { get; set; } // 配置10秒轮询间隔,可按需调整 private readonly PeriodicTimer _pollingTimer = new(TimeSpan.FromSeconds(10)); private readonly CancellationTokenSource _cts = new(); protected override async Task OnInitializedAsync() { // 页面加载时先拉取一次初始数据 FinishedCount = await ProductionDataService.GetFinishedCountAsync(); // 后台启动轮询任务,不阻塞页面渲染 _ = RunPollingTaskAsync(); } private async Task RunPollingTaskAsync() { try { while (await _pollingTimer.WaitForNextTickAsync(_cts.Token)) { FinishedCount = await ProductionDataService.GetFinishedCountAsync(); // 通知UI刷新 StateHasChanged(); } } catch (OperationCanceledException) { // 页面销毁时主动取消任务,该异常为正常逻辑无需处理 } } public async ValueTask DisposeAsync() { // 销毁时释放资源,避免内存泄漏 _cts.Cancel(); _pollingTimer.Dispose(); await _cts.DisposeAsync(); } }
注:如果使用.NET 5及更低版本,可将
PeriodicTimer替换为System.Threading.Timer,逻辑完全一致。
优缺点
- 优点:代码量少、逻辑简单无额外依赖、稳定性极高
- 缺点:数据更新存在最长10秒的延迟
优化建议
如果在线用户量较大,可在服务端增加内存缓存存储计数数据,后台单独线程每1秒刷新一次缓存,所有轮询请求直接读缓存,大幅降低数据库查询压力。
方案2:变更实时推送(延迟最低,适合强实时场景)
该方案可实现数据库更新后1秒内同步到前端页面,依赖Blazor Server内置的SignalR通信能力实现。
实现步骤
- 首先定义单例通知服务,用于跨组件传递数据更新事件:
public interface IProductionUpdateNotifier { event Action OnDataUpdated; void PublishUpdateSignal(); } public class ProductionUpdateNotifier : IProductionUpdateNotifier { public event Action OnDataUpdated; public void PublishUpdateSignal() => OnDataUpdated?.Invoke(); }
- 在
Program.cs中注册为全局单例:
builder.Services.AddSingleton<IProductionUpdateNotifier, ProductionUpdateNotifier>();
- 触发更新信号:
- 如果可修改设备的写入逻辑:设备写完数据库后,调用服务端提供的极简API,API内部直接调用
PublishUpdateSignal()方法发布更新信号即可 - 如果无法修改设备逻辑:可对接使用的数据库原生变更通知能力(如SQL Server的SqlDependency、PostgreSQL的LISTEN/NOTIFY),监听到目标表数据变更时调用
PublishUpdateSignal()即可
- 如果可修改设备的写入逻辑:设备写完数据库后,调用服务端提供的极简API,API内部直接调用
- Blazor页面订阅更新事件:
@implements IAsyncDisposable @inject IProductionUpdateNotifier UpdateNotifier @inject IProductionDataService ProductionDataService <p>当前完工工件数量:@FinishedCount</p> @code { private int FinishedCount { get; set; } protected override async Task OnInitializedAsync() { FinishedCount = await ProductionDataService.GetFinishedCountAsync(); // 订阅数据更新事件 UpdateNotifier.OnDataUpdated += RefreshData; } private async void RefreshData() { FinishedCount = await ProductionDataService.GetFinishedCountAsync(); // 事件回调可能不在UI线程,需通过InvokeAsync触发UI刷新 await InvokeAsync(StateHasChanged); } public ValueTask DisposeAsync() { // 页面销毁时取消订阅,避免内存泄漏 UpdateNotifier.OnDataUpdated -= RefreshData; return ValueTask.CompletedTask; } }
优缺点
- 优点:数据延迟极低,基本可实现变更即同步,用户量大时也不会产生过多数据库查询压力
- 缺点:需要额外对接信号触发逻辑,不同数据库的变更通知实现不通用
优化建议
可将计数结果存在全局内存缓存中,收到更新信号时仅刷新一次缓存,所有页面直接读缓存,进一步降低数据库负载。
选型建议
- 如果10秒以内的延迟完全可接受,优先选择定时轮询方案,维护成本极低,基本不会出现线上问题
- 如果需要实时同步数据且可修改设备写入逻辑,优先选择主动推送方案
- 只有在无法修改设备逻辑且必须实时同步的场景下,再考虑对接数据库原生变更通知能力
内容的提问来源于stack exchange,提问作者BTOM
相关产品推荐
相关产品推荐

