Hangfire 1.5.3 System.MissingMethodException 在我们所有的工作上
Hangfire 1.5.3 System.MissingMethodException on all our jobs
我们刚刚将 hangfire 从 1.3.4 更新到 1.5.3。
我们的创业公司从此发生了变化:
private static void DoHangfire(IAppBuilder app)
{
var options = new BackgroundJobServerOptions
{
// Set thread count to 1
WorkerCount = 1
};
app.UseHangfire(config =>
{
config.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["JobsDB"].ConnectionString);
config.UseAuthorizationFilters(new HangfireDashboardAuthorizationFilter());
config.UseServer(options);
});
// Set retries to zero
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
JobActivator.Current = new WindsorJobActivator(Container.Kernel);
}
对此:
private static void DoHangfire(IAppBuilder app)
{
var options = new BackgroundJobServerOptions
{
// Set thread count to 1
WorkerCount = 1
};
GlobalConfiguration.Configuration.UseSqlServerStorage(
ConfigurationManager.ConnectionStrings["JobsDB"].ConnectionString);
app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
AuthorizationFilters = new List<IAuthorizationFilter>
{
new HangfireDashboardAuthorizationFilter()
}
});
app.UseHangfireServer(options);
// Set retries to zero
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
JobActivator.Current = new WindsorJobActivator(Container.Kernel);
}
现在我们所有的作业(我们有 4 种不同类型的作业)立即失败并出现此错误:
System.MissingMethodException: No parameterless constructor defined
for this object. at
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean
publicOnly, Boolean noCheck, Boolean& canBeCached,
RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean
skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,
Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at
System.Activator.CreateInstance(Type type) at
Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type) at
Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext
context) at
Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass3.b__0()
at
Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter
filter, PerformingContext preContext, Func1 continuation) at
Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext
context, IEnumerable
1 filters) at
Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context,
IStorageConnection connection, String jobId)
好吧,这个问题与新版本的 Hangfire 如何与 Hangfire.Windsor 包交互有关,它只是提供一个自定义的 JobActivator 和一个用于服务定位的 windsor 容器。
通过移动
JobActivator.Current = new WindsorJobActivator(Container.Kernel);
在对 app.UseHangfireServer() 的调用之上,我们能够发现真正的异常消息,这是一个 Castle.MicroKernel.ComponentNotFoundException 通知我们它无法连接包含我们想要的方法的依赖项hangfire 到 运行。
可以这么说,在 1.3.4 中,运行 一份工作你可以这样做:
BackgroundJob.Enqueue(() => thingWhichDoesStuff.DoStuff());
其中 thingWhichDoesStuff 被注入到包含 class 中并且 hangfire.windsor JobActivator 神奇地能够解析为该类型。
然而在 1.5.3 中这个神奇的解决方案不再发生,所以你必须明确地告诉 JobActivator 包含你想要 hangfire 的方法的类型的接口 运行:
BackgroundJob.Enqueue<IDoStuff>(x => x.DoStuff());
这会导致我们所有的作业重新开始工作。
我们刚刚将 hangfire 从 1.3.4 更新到 1.5.3。
我们的创业公司从此发生了变化:
private static void DoHangfire(IAppBuilder app)
{
var options = new BackgroundJobServerOptions
{
// Set thread count to 1
WorkerCount = 1
};
app.UseHangfire(config =>
{
config.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["JobsDB"].ConnectionString);
config.UseAuthorizationFilters(new HangfireDashboardAuthorizationFilter());
config.UseServer(options);
});
// Set retries to zero
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
JobActivator.Current = new WindsorJobActivator(Container.Kernel);
}
对此:
private static void DoHangfire(IAppBuilder app)
{
var options = new BackgroundJobServerOptions
{
// Set thread count to 1
WorkerCount = 1
};
GlobalConfiguration.Configuration.UseSqlServerStorage(
ConfigurationManager.ConnectionStrings["JobsDB"].ConnectionString);
app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
AuthorizationFilters = new List<IAuthorizationFilter>
{
new HangfireDashboardAuthorizationFilter()
}
});
app.UseHangfireServer(options);
// Set retries to zero
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
JobActivator.Current = new WindsorJobActivator(Container.Kernel);
}
现在我们所有的作业(我们有 4 种不同类型的作业)立即失败并出现此错误:
System.MissingMethodException: No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type) at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass3.b__0() at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable
1 filters) at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)
好吧,这个问题与新版本的 Hangfire 如何与 Hangfire.Windsor 包交互有关,它只是提供一个自定义的 JobActivator 和一个用于服务定位的 windsor 容器。
通过移动
JobActivator.Current = new WindsorJobActivator(Container.Kernel);
在对 app.UseHangfireServer() 的调用之上,我们能够发现真正的异常消息,这是一个 Castle.MicroKernel.ComponentNotFoundException 通知我们它无法连接包含我们想要的方法的依赖项hangfire 到 运行。
可以这么说,在 1.3.4 中,运行 一份工作你可以这样做:
BackgroundJob.Enqueue(() => thingWhichDoesStuff.DoStuff());
其中 thingWhichDoesStuff 被注入到包含 class 中并且 hangfire.windsor JobActivator 神奇地能够解析为该类型。
然而在 1.5.3 中这个神奇的解决方案不再发生,所以你必须明确地告诉 JobActivator 包含你想要 hangfire 的方法的类型的接口 运行:
BackgroundJob.Enqueue<IDoStuff>(x => x.DoStuff());
这会导致我们所有的作业重新开始工作。