You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 14:40:33