Hangfire 处理定义为 SingleInstance 的 autofac 依赖项

Posted

技术标签:

【中文标题】Hangfire 处理定义为 SingleInstance 的 autofac 依赖项【英文标题】:Hangfire disposes of autofac dependencies which are defined as SingleInstance 【发布时间】:2015-03-23 12:47:16 【问题描述】:

在 ASP.NET 应用程序中使用 hangfire 1.3.4 和 hangfire.autofac 1.0.0。 我有以下情况:

 class MyType : IDisposable 
 
      public void Start()
      
          RecurringJob.AddOrUpdate("background-update", () => ProcessData(), Cron.Daily());
          RecurringJob.Trigger("background-update"); 
      

     public void ProcessData()...

     public void Dispose()... 
 
 ...
 var builder = new ContainerBuilder();
 builder.RegisterType<MyType>().SingleInstance();
 var cont = builder.Build();
 app.UseHangfire(config =>
        
            var options = new SqlServerStorageOptions();
            config.UseAutofacActivator(cont);
            config.UseSqlServerStorage("MyServer", options);
            config.UseServer();
        );

...
var c = cont.Resolve<MyType>();
c.Start();

我看到的是 Autofac 按请求执行循环作业,但随后处理 MyType 的实例,这显然会导致后续调用失败,因为它被定义为单例,并且应该由 Autofac 在关闭时处理。

是我遗漏了什么还是这是一个错误?

这是调用堆栈:

MyDll.dll!MyType.Dispose() 第 316 行 C# Hangfire.Core.dll!Hangfire.Common.Job.Dispose(对象实例)未知 Hangfire.Core.dll!Hangfire.Common.Job.Perform(Hangfire.JobActivator 激活器,Hangfire.IJobCancellationToken cancelToken)未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.PerformJobWithFilters.AnonymousMethod__6() 未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.InvokePerformFilter(Hangfire.Server.IServerFilter 过滤器,Hangfire.Server.PerformingContext preContext,System.Func 延续)未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.PerformJobWithFilters.AnonymousMethod__8() 未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.InvokePerformFilter(Hangfire.Server.IServerFilter 过滤器,Hangfire.Server.PerformingContext preContext,System.Func 延续)未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.PerformJobWithFilters.AnonymousMethod__8() 未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.PerformJobWithFilters(Hangfire.Server.PerformContext 上下文,Hangfire.Server.IJobPerformer 执行者,System.Collections.Generic.IEnumerable 过滤器)未知 Hangfire.Core.dll!Hangfire.Server.JobPerformanceProcess.Run(Hangfire.Server.PerformContext 上下文,Hangfire.Server.IJobPerformer 执行者)未知 Hangfire.Core.dll!Hangfire.Server.Worker.ProcessJob(string jobId, Hangfire.Storage.IStorageConnection 连接, Hangfire.Server.IJobPerformanceProcess 进程, System.Threading.CancellationToken shutdownToken) 未知 Hangfire.Core.dll!Hangfire.Server.Worker.Execute(System.Threading.CancellationToken cancelToken) 未知 Hangfire.Core.dll!Hangfire.Server.AutomaticRetryServerComponentWrapper.ExecuteWithAutomaticRetry(System.Threading.CancellationTokencancellationToken) 未知 Hangfire.Core.dll!Hangfire.Server.AutomaticRetryServerComponentWrapper.Execute(System.Threading.CancellationToken cancelToken) 未知 Hangfire.Core.dll!Hangfire.Server.ServerSupervisor.ExecuteComponent() 未知 Hangfire.Core.dll!Hangfire.Server.ServerSupervisor.RunComponent() 未知 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(对象状态)未知 mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback 回调, 对象状态, bool preserveSyncCtx) 未知 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback 回调, 对象状态, bool preserveSyncCtx) 未知 mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback 回调, 对象状态) 未知 mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() 未知 [本机到托管转换]

【问题讨论】:

您能否在dispose 方法上放置一个断点并查看调用堆栈以确定为什么要处理此类型?如果您需要帮助,请编辑您的问题并包含调用堆栈。 发布了调用栈 如果我们查看 HangFire 的来源,我们可以看到它管理对象的生命周期,并且不让 Autofac 做。查看Job.cs 的第 97 行。为什么需要单例? 解决方法确实是不使用单例。但我认为这指向了 Hangfire-Autofac(可能还有其他 DI 框架)集成中的一个错误。如果对象不是由 Hangfire 实例化,而是由 DI 容器实例化,我相信它不应该 Dispose ,而是让容器完成它的工作。 我不知道 Hangfire 但在查看源代码后我同意你的观点,它看起来像 Hangfire 中的设计错误 :-( 【参考方案1】:

此问题已在 hangfire 的最新(测试版)版本中得到修复,详情请参阅 https://github.com/HangfireIO/Hangfire/issues/329。

【讨论】:

以上是关于Hangfire 处理定义为 SingleInstance 的 autofac 依赖项的主要内容,如果未能解决你的问题,请参考以下文章

当 Hangfire 并行处理多个作业时,为啥 MySQL InnoDB 会产生如此多的死锁?

Hangfire项目实践

hangfire 相关

Hangfire 定时任务设置某个时间区间每隔一定时间触发的Cron表达式

asp.net core 中hangfire面板的配置及使用

Hangfire实战一