.NET Core 6 Blazor Server组件Dispose未触发,定时器无法终止问题
Blazor Server组件Dispose未触发导致定时器持续运行问题
我们有一个.NET Core 6应用,正逐步将UI功能从JS迁移至Blazor Server组件。大部分功能运行正常,但引入的带定时器的组件(用于刷新网络状态等用户操作外变更的内容)存在问题:离开组件所在页面时,组件的Dispose方法从未被调用,导致定时器持续运行。
组件调用方式
<component type="typeof(APStatus)" render-mode="Server" />
定时器相关代码
OnInitializedAsync中定时器初始化
_timer = new System.Timers.Timer(10000); _timer.Elapsed += CountDownTimer; _timer.Start(); _timer.Enabled = true;
CountDownTimer回调方法
public async void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e) { if (_internalCounter > 0) { _internalCounter -= 1; } else { _timer.Enabled = false; _timer.Stop(); } await InvokeAsync(async () => { if (NetInfo != null) { await GetApStatus(); } }); }
Dispose方法实现
public void Dispose() { System.Diagnostics.Debug.WriteLine("Disposing Happened"); _timer.Enabled = false; _timer.Stop(); _timer.Dispose(); _timer = null; }
CircuitHandler相关问题
添加了CircuitHandler后,能触发OnCircuitOpenAsync事件,但OnCircuitClosedAsync从未触发,代码如下:
public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken) { Console.WriteLine("OnCircuitClosedAsync"); Circuits.TryRemove(circuit.Id, out var circuitRemoved); OnCircuitsChanged(); return base.OnCircuitClosedAsync(circuit, cancellationToken); }
已尝试的排查手段
- 检查Program.cs配置
- 更换组件调用方式
- 查看Chrome开发者工具,无异常日志
- 开启Blazor日志,未发现问题
- 搜索技术论坛,未找到同类问题原因
- 升级至最新.NET Core 6包,无效
项目中其他Blazor组件运行正常,但它们的Dispose方法也从未触发。
对比测试:新建项目vs现有项目
在新建项目中实现Microsoft官方定时器组件示例,页面跳转时Dispose正常触发;但将该组件复制到现有项目后,页面跳转时Dispose仍未触发,示例代码如下:
@page "/counter" @using System.Timers @using System.Diagnostics @implements IDisposable <PageTitle>Counter</PageTitle> <h1>Counter</h1> <p>Current count: @currentCount</p> <p>Current count: @timerCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } private int timerCount = 0; private Timer timer = new(1000); protected override void OnInitialized() { timer.Elapsed += (sender, eventArgs) => OnTimerCallback(); timer.Start(); } private void OnTimerCallback() { _ = InvokeAsync(() => { timerCount++; StateHasChanged(); }); } public void Dispose() { Debug.WriteLine("Disposing"); timer.Dispose(); } }
更新1:调整Circuit配置缩短销毁时间
经过大量关于Circuit的研究和调整,在Program.cs中设置了DisconnectedCircuitRetentionPeriod:
builder.Services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromSeconds(10); });
这将组件销毁时间从约3.5分钟缩短至10秒以内,虽仍在探究根本原因,但已取得进展。
更新2:问题解决验证
经测试,该设置解决了所有Blazor组件的Dispose问题,未引发其他异常。后续研究发现相关技术问答也表明此配置可解决组件销毁类问题,希望能帮助其他开发者。
内容的提问来源于stack exchange,提问作者Jim Miller
相关产品推荐
相关产品推荐

