Blazor Server页面API数据定时刷新UI失效问题求助
Blazor定时器更新数据后UI不刷新的解决方案
核心问题分析
你的代码中使用System.Timers.Timer的Elapsed事件触发异步操作,存在两个关键问题:
async void的事件处理程序会导致线程上下文管理混乱,异常无法被正确捕获- 直接替换
List<Horse>实例可能让Blazor的变更检测无法及时识别数据变化
修复后的完整代码
@page "/" @using DerbyStonks.Blazor.Services.Derby.Entities @using System.Threading @inject IHttpClientFactory ClientFactory @inject NavigationManager NavigationManager @implements IDisposable <PageTitle>Home</PageTitle> <br/> <h1>Horses</h1> @if (_loading) { <h3>Loading ...</h3> } else { <ul class="horse-list"> @foreach (Horse horse in _horses) { <li class="horse-list-item"> <h2>#@horse.Number: @horse.Name</h2> </li> } </ul> } @code { private Timer _timer; private bool _loading = true; private List<Horse> _horses = new List<Horse>(); private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); protected override async Task OnInitializedAsync() { await LoadHorses(); StartHotReload(); } private void StartHotReload() { _timer = new Timer(async _ => { await LoadHorsesAndUpdateUI(); }, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); } private async Task LoadHorsesAndUpdateUI() { if (!await _semaphore.WaitAsync(TimeSpan.Zero)) { return; } try { await LoadHorses(); await InvokeAsync(() => StateHasChanged()); } catch (Exception ex) { // 添加日志记录逻辑 } finally { _semaphore.Release(); } } private async Task LoadHorses() { HttpClient client = ClientFactory.CreateClient(); client.BaseAddress = new Uri(NavigationManager.BaseUri); _loading = true; try { var horses = await client.GetFromJsonAsync<List<Horse>>("api/Horses"); if (horses != null) { _horses.Clear(); _horses.AddRange(horses); } else { _horses.Clear(); } } finally { _loading = false; } } public void Dispose() { _timer?.Dispose(); _semaphore?.Dispose(); } }
关键修改说明
- 替换定时器类型:使用
System.Threading.Timer替代System.Timers.Timer,避免async void事件处理带来的线程上下文问题 - 显式实现IDisposable:添加
@implements IDisposable,确保组件销毁时定时器和信号量能被正确释放 - 并发请求控制:用
SemaphoreSlim防止短时间内多个API请求同时执行,避免状态冲突 - 优化数据更新逻辑:将直接替换
_horses实例改为清空后添加新数据,让Blazor变更检测更容易识别集合变化 - 明确状态变更调用:通过
InvokeAsync(() => StateHasChanged())确保状态变更通知在UI线程执行
内容的提问来源于stack exchange,提问作者bmeehan23
相关产品推荐
相关产品推荐

