我遇到了 Hangfire 无法在 NET 5 上的 Web API 中处理其实例对象的问题。
这是我在“ConfigureServices()”中的配置(非常标准,顺便说一句):
services.AddScoped<ITestService, TestService>(); // I have also tried with "AddTransient()"
services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("Default")));
services.AddHangfireServer();
然后,我有以下行在“Configure()”中配置重复作业:
public void Configure(IApplicationBuilder app,
IWebHostEnvironment env,
IHttpContextAccessor httpContextAccessor,
ITestService testService)
{
// Omitting other configure code here
RecurringJob.AddOrUpdate("Check", () => testService.Test(), Cron.Minutely); // You can try "*/1 * * * ? *" to speed it up
}
如您所见,“ITestService”是通过 IoC 注入的。
仅供参考,“ITestService”是一个“IDisposable”。如果我在构造函数和“Dispose()”方法中都放置断点,则每个间隔都会调用构造函数,而永远不会调用“Dispose()”。
这对我来说是一个问题,因为服务本身还有其他依赖项,例如存储库(即:SQL 连接)。每当时间过去,应用程序就会开始崩溃,因为它失去了池中的连接:
失败:Hangfire.Processing.BackgroundExecution[0] 由于异常,Execution Worker 现在处于 Failed 状态,将在 00:05:00 以内重试执行 System.InvalidOperationException:超时已过期。从池中获取连接之前超时时间已过。发生这种情况可能是因为所有池连接都在使用中并且达到了最大池大小。
如果我没记错的话,这个错误与未处理 SQL 连接有关。
我做错了什么吗?或者这可能是一个错误?
如果我将“this.Dispose()”放在 TestService.Test() 的末尾,并在那里手动处置存储库,则可以修复之前的错误。但我认为这不是一个正确的解决方案:S.
正如评论中所说,你应该使用:
RecurringJob.AddOrUpdate<ITestService>("Check", t => t.Test(), Cron.Minutely);
以这种方式调用该方法将触发
ITestServer
的依赖注入,并且实例将遵循预期的生命周期,并需要调用 Dispose()