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

