Hangfire 1.5.3 System.MissingMethodException on al

2019-07-15 05:05发布

问题:

We just updated hangfire from 1.3.4 to 1.5.3.

Our startup has changed from this:

    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);
    }

to this:

    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);
    }

Now all our jobs (we have 4 different kinds of jobs) fail immediately with this error:

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, IEnumerable1 filters) at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

回答1:

Well the problem had to do with some magic in how the new version of Hangfire interacted with the Hangfire.Windsor package, which simply provides a custom JobActivator with a windsor container for service location.

By moving the

JobActivator.Current = new WindsorJobActivator(Container.Kernel);

above the call to app.UseHangfireServer() we were able to uncover the real exception message, which was a Castle.MicroKernel.ComponentNotFoundException informing us that it couldn't wire in the dependency containing the method we wanted hangfire to run.

Suffice to say, in 1.3.4, to run a job you can do this:

BackgroundJob.Enqueue(() => thingWhichDoesStuff.DoStuff()); 

where thingWhichDoesStuff is injected into the containing class and the hangfire.windsor JobActivator is just magically able to resolve to the type.

However in 1.5.3 this magic resolution no longer happens, so you must explicitly tell the JobActivator the interface of the type containing the method you want hangfire to run:

BackgroundJob.Enqueue<IDoStuff>(x => x.DoStuff());  

This causes all our jobs to start working again.



标签: c# hangfire