Blazor Server(.NET 8)应用中Timer无法正常工作的问题
Blazor Server(.NET 8)应用中Timer无法正常工作的问题
嗨,我来帮你分析并解决这个问题,你的代码里有两个核心问题导致Timer表现异常:
后台线程无法直接更新UI:
System.Timers.Timer的Elapsed事件是在后台线程触发的,而Blazor的UI更新必须在组件的同步上下文(也就是UI线程)里执行,直接修改StatusMessage不会触发组件重新渲染,甚至可能引发线程安全问题。重复绑定事件导致多次触发:每次点击Start按钮,你都会执行
timerCounter.Elapsed += TimerCounter_Elapsed;,这会让同一个事件被绑定多次,Timer每触发一次,Countdown--就会执行多次,所以你会看到数字跳着减少(比如从100直接跳到97)。
修复后的完整代码
@page "/" @using System.Timers @rendermode InteractiveServer @implements IAsyncDisposable <p>@StatusMessage</p> <button class="btn btn-primary" @onclick="StartHandler">Start</button> @code { private void StartHandler() { // 重置倒计时初始值并更新UI Countdown = 100; StatusMessage = $"{Countdown}"; // 先移除旧的事件绑定,避免重复触发 timerCounter.Elapsed -= TimerCounter_Elapsed; // 设置Timer参数 timerCounter.Interval = 1000; timerCounter.Elapsed += TimerCounter_Elapsed; timerCounter.AutoReset = true; timerCounter.Start(); } private async void TimerCounter_Elapsed(object? sender, ElapsedEventArgs e) { Countdown--; // 切换到UI线程更新状态并触发组件渲染 await InvokeAsync(() => { StatusMessage = $"{Countdown}"; StateHasChanged(); }); // 可选逻辑:倒计时结束后自动停止Timer if (Countdown <= 0) { timerCounter.Stop(); } } private Timer timerCounter = new Timer(); private int Countdown = 0; private string StatusMessage = ""; // 组件销毁时清理Timer资源,避免内存泄漏 public async ValueTask DisposeAsync() { timerCounter.Elapsed -= TimerCounter_Elapsed; timerCounter.Stop(); timerCounter.Dispose(); await Task.CompletedTask; } }
关键修改说明
- 实现
IAsyncDisposable接口,在组件销毁时停止并释放Timer,防止内存泄漏; - 在
StartHandler中先移除旧的Elapsed事件绑定,再重新绑定,避免多次触发同一逻辑; - 在
TimerCounter_Elapsed方法中用InvokeAsync包裹状态更新和StateHasChanged(),确保操作在UI线程执行,触发组件重新渲染; - 增加了倒计时结束自动停止Timer的逻辑,让功能更完整。
备注:内容来源于stack exchange,提问作者max
相关产品推荐
相关产品推荐

