ASP.NET Core中IHostedService报对象已释放错误该如何正确实现?
问题根因
你触发ObjectDisposedException的核心原因是构造函数中的服务作用域被提前释放:
- 构造函数中你用
using语句创建了IServiceScope,当using代码块执行结束后,整个scope包括其下的ServiceProvider都会被自动销毁,你赋值的_provider本质是已经被释放的对象,后续Timer回调调用Purge方法访问该对象时就会抛出释放异常。
同时你的代码还存在3个功能性问题:
- 时间判断逻辑完全错误:要删除超过留存时长的通知,应该筛选创建时间早于当前时间减去留存时长的记录,你当前写的
CreatedDate > {deletedate}(且deletedate是当前时间加留存时长)完全匹配不到需要删除的数据 - 只拼接了SQL字符串,没有实际执行删除操作
- Timer回调没有处理异步和异常,一旦触发未捕获异常会直接导致后台服务崩溃
修正后的完整代码
public class PurgeService : IHostedService, IDisposable { private readonly IServiceProvider _rootProvider; private Timer _timer; // 直接注入根服务提供者,不要提前创建scope public PurgeService(IServiceProvider rootProvider) { _rootProvider = rootProvider; } public void Dispose() { _timer?.Dispose(); } // 每次执行任务时单独创建作用域 private async Task Purge() { try { // 为本次任务创建独立的服务作用域,执行完自动释放 using var scope = _rootProvider.CreateScope(); var serviceProvider = scope.ServiceProvider; var dbContext = serviceProvider.GetRequiredService<ApplicationDBContext>(); var setting = await dbContext.AppSet.FirstAsync(); // 计算删除阈值:当前时间 减去 允许留存的小时数,早于该时间的通知需要删除 var deleteThreshold = DateTime.Now.AddHours(-setting.PurgeTimer); // 执行SQL删除,Interpolated方式避免SQL注入风险 await dbContext.Database.ExecuteSqlInterpolatedAsync( $"DELETE FROM Notifications WHERE CreatedDate < {deleteThreshold}" ); } catch (Exception ex) { // 此处可接入日志组件记录错误,避免服务意外崩溃 } } public Task StartAsync(CancellationToken cancellationToken) { // 适配异步方法,避免async void导致的异常逃逸问题 _timer = new Timer(async _ => await Purge(), null, TimeSpan.Zero, TimeSpan.FromSeconds(10)); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _timer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } }
注册逻辑
原有注册逻辑不需要修改,保持以下代码即可:
services.AddHostedService<PurgeService>();
内容的提问来源于stack exchange,提问作者T0bi
相关产品推荐
相关产品推荐

