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

Blazor Server模式下刷新页面时如何立即清理Timer资源?

解决Blazor Server页面刷新/导航时立即清理Timer的问题

在.NET 8 RC1的Blazor Server应用中,组件的Dispose方法会因SignalR连接超时(默认2-3分钟)延迟执行,导致刷新页面后旧Timer实例持续运行。要避免这种情况,需主动在页面离开时清理Timer,以下是两种可靠的实现方式:

方法一:监听NavigationManager导航事件

利用NavigationManager的LocationChanged事件捕获页面刷新、路由跳转等离开操作,立即停止并释放Timer:

@page "/timer-page"
@inject NavigationManager NavManager
@implements IDisposable

<h3>Timer Demo Page</h3>

@code {
    private System.Timers.Timer? _timer;
    private IDisposable? _navigationSubscription;

    protected override void OnInitialized()
    {
        // 初始化Timer,每秒执行一次回调
        _timer = new System.Timers.Timer(1000);
        _timer.Elapsed += TimerElapsed;
        _timer.Start();

        // 订阅导航变化事件
        _navigationSubscription = NavManager.LocationChanged += OnLocationChanged;
    }

    private void TimerElapsed(object? sender, System.Timers.ElapsedEventArgs e)
    {
        // Timer执行的业务逻辑
        Console.WriteLine($"Timer tick: {DateTime.Now:HH:mm:ss}");
    }

    private void OnLocationChanged(object? sender, LocationChangedEventArgs e)
    {
        // 导航离开时停止并清理Timer
        _timer?.Stop();
        _timer?.Dispose();
        _timer = null;
    }

    public void Dispose()
    {
        // 清理事件订阅和Timer资源
        _navigationSubscription?.Dispose();
        _timer?.Stop();
        _timer?.Dispose();
    }
}

说明:

  • LocationChanged事件会在页面刷新、前进后退、路由跳转时触发,能及时捕获用户离开当前页面的操作
  • 操作Timer时先调用Stop()(或Change(Timeout.Infinite, Timeout.Infinite))停止计时,再执行Dispose,避免回调逻辑在清理后仍执行

方法二:结合CancellationToken实现可控取消

通过CancellationTokenSource生成取消令牌,在导航离开时触发取消,Timer回调中检查令牌状态并自行清理:

@page "/timer-page"
@inject NavigationManager NavManager
@implements IDisposable

<h3>Timer Demo Page</h3>

@code {
    private System.Timers.Timer? _timer;
    private CancellationTokenSource _cts = new();
    private IDisposable? _navigationSubscription;

    protected override void OnInitialized()
    {
        _timer = new System.Timers.Timer(1000);
        // 将取消令牌传入Timer回调
        _timer.Elapsed += (s, e) => TimerElapsed(_cts.Token);
        _timer.Start();

        _navigationSubscription = NavManager.LocationChanged += (s, e) => _cts.Cancel();
    }

    private void TimerElapsed(CancellationToken cancellationToken)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            // 令牌取消时停止并清理Timer
            _timer?.Stop();
            _timer?.Dispose();
            _timer = null;
            return;
        }

        Console.WriteLine($"Timer tick: {DateTime.Now:HH:mm:ss}");
    }

    public void Dispose()
    {
        _navigationSubscription?.Dispose();
        _cts.Cancel();
        _cts.Dispose();
        _timer?.Stop();
        _timer?.Dispose();
    }
}

核心思路:
Blazor Server组件的生命周期依赖SignalR连接,页面刷新后旧连接不会立即断开,导致Dispose延迟执行。因此必须主动监听导航事件,在用户离开页面时立即清理Timer资源,而不是依赖组件的Dispose方法。

内容的提问来源于stack exchange,提问作者zyash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 01:14:56