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

Blazor Server应用Hangfire定时任务中服务未注入问题咨询

错误原因

  1. 你的判断部分正确,但核心问题并非单例服务无法跨线程调用,而是Hangfire执行调度任务时,已经脱离了原页面的FetchData组件实例上下文:
    • Blazor组件实例仅在用户访问对应页面期间存活,页面关闭、组件销毁后实例就会被释放
    • Hangfire调度时只会序列化方法调用信息,执行时会重新创建对应类的实例,而非复用用户页面内的组件实例,新实例没有经过Blazor的依赖注入流程,所以ForecastService属性自然为null
    • 就算解决了注入问题,Hangfire更新的也是新实例的forecasts字段,和用户浏览器里渲染的组件实例完全无关,UI也不会刷新,本质是你选错了定时工具,Hangfire是全局后台任务调度组件,不适合做组件内的UI定时更新
  2. 线程安全的单例服务完全支持跨多线程使用,你当前的WeatherForecastService没有共享可变状态,跨线程调用没有任何问题

解决方案

直接使用.NET自带的System.Threading.Timer实现组件内定时刷新,修改FetchData.razor代码即可:
首先在组件顶部新增实现IDisposable的声明:

@page "/fetchdata"
@implements IDisposable
@using WeatherTest.Data

@inject WeatherForecastService ForecastService

然后修改@code块逻辑:

@code {
    private WeatherForecast[] forecasts;
    private System.Threading.Timer _updateTimer;

    public async Task UpdateForecasts()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
        // 通知Blazor需要刷新UI
        StateHasChanged();
    }

    protected override async Task OnInitializedAsync()
    {
        await UpdateForecasts();
        // 初始化定时器:延迟5秒首次执行,之后每5秒执行一次
        _updateTimer = new System.Threading.Timer(
            async _ => await UpdateForecasts(),
            null,
            TimeSpan.FromSeconds(5),
            TimeSpan.FromSeconds(5));
    }

    // 组件销毁时释放定时器,避免内存泄漏
    public void Dispose()
    {
        _updateTimer?.Dispose();
    }
}

不需要修改其他服务配置,也不需要依赖Hangfire就可以实现需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:15:08