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

Blazor Server定时更新数据按F5刷新触发System.ObjectDisposedException求解

报错根本原因

该异常的核心诱因是Blazor组件生命周期与System.Threading.Timer异步回调的执行时机冲突,具体逻辑如下:

  • Blazor Server模式下,用户按下F5刷新页面时,当前页面对应的组件会立即触发销毁流程,组件绑定的渲染器(Renderer)会被优先标记为已释放状态
  • System.Threading.Timer的回调委托签名为void TimerCallback(object state),你传入的异步lambda会被编译为async void类型,这类异步回调的执行不会被.NET运行时追踪等待
  • 你在Dispose方法中调用_timer.Dispose()仅能停止定时器调度后续的新回调,已经启动执行的回调不会被终止。当这个正在运行的回调走完await TimerProcessGetValue()/await Task.Delay(500)逻辑后,再执行await InvokeAsync(StateHasChanged)时,渲染器已经被释放,就会抛出ObjectDisposedException。

三种测试方案的生效/失效原理

  • ① 带WaitHandle参数的Timer.Dispose方案失效:WaitHandle仅会等待所有已排队未启动的回调执行完成,已经进入执行状态的异步回调中的await逻辑不在Timer的管控范围内,所以等待500ms也无法拦截已经运行中的回调调用StateHasChanged。
  • ② 改用System.Timers.Timer方案生效:System.Timers.Timer的Elapsed事件默认会吞掉所有回调内的未捕获异常,即使InvokeAsync抛出了释放异常,也会被Timer内部消化,不会向上抛出报错。
  • ③ 增加异常捕获方案生效:直接捕获了回调内抛出的释放异常,主动忽略后自然不会触发展示报错。

推荐的标准修复方案

相比上述三种方案,更规范的实现是增加组件销毁标记位,从逻辑上避免销毁后调用渲染接口,不会吞掉正常业务异常也没有多余开销:

@code {
    // 新增组件销毁标记
    private bool _disposed;

    protected override void OnInitialized()
    {
        // 原有初始化逻辑保持不变
        using (var dbContext = DbFactory.CreateDbContext())
        {
            this.recipes = dbContext.Recipes.ToList();
            this.planOrders = dbContext.PlanOrders.ToList();
            this.nowOrders = dbContext.NowOrders.ToList();
        }

        _timer = new System.Threading.Timer(async (_) =>
        {
            Time = DateTime.Now.ToString();
            databaseValue = await TimerProcessGetValue();
            // 先判断组件状态再执行渲染
            if (!_disposed)
            {
                await InvokeAsync(StateHasChanged);    
            }
        }, null, 0, 1000);
    }

    public void Dispose() 
    {
        // 先标记销毁再释放定时器
        _disposed = true;
        _timer?.Dispose();
    }

    // 原有其他逻辑保持不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:06:05