.NET 4.6.1下Windows Service集成Hangfire任务不执行问题排查
场景描述
将现有控制台应用转换为Windows Service,目标是通过Hangfire按调度执行原有任务。已完成集成Hangfire的Windows Service开发,服务可正常构建并启动,但任务始终未执行,日志报依赖实例化相关错误。
核心代码
服务构造函数
public BatchService(ILogger<BatchService> logger) { InitializeComponent(); GlobalConfiguration.Configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseColouredConsoleLogProvider() .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseSqlServerStorage(Constants.ConnectionString.Peach, new SqlServerStorageOptions { CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), QueuePollInterval = TimeSpan.Zero, UseRecommendedIsolationLevel = true }) .UseNLogLogProvider(); _logger = logger; }
Hangfire配置加载与启停方法
private void LoadConfigurationIntoHangfire() { // 加载任务配置 var jobListing = Configuration.GetJobConfiguration().Where(job => job.JobType.Equals("CRON")).ToList(); // 调试日志 _logger.LogDebug($"LoadConfigurationIntoHangfire() - jobListing = {JsonConvert.SerializeObject(jobListing)}"); foreach (var job in jobListing) { // 信息日志 _logger.LogInformation($"添加/更新任务 '{job.JobName}',Cron表达式为 '{job.CronExpression}'。"); RecurringJob.AddOrUpdate<IDataProtectionJob>(x => x.ExecuteJob(job), job.CronExpression); } } private void StopHangfire() { // 信息日志 _logger.LogInformation("正在停止Hangfire。"); _hangfireServer.SendStop(); _hangfireServer.WaitForShutdown(new TimeSpan(0, 0, 5)); _hangfireServer.Dispose(); // 信息日志 _logger.LogInformation("Hangfire已停止。"); } private void StartHangfire() { // 信息日志 _logger.LogInformation("正在启动Hangfire。"); _hangfireServer = new BackgroundJobServer(); LoadConfigurationIntoHangfire(); // 信息日志 _logger.LogInformation("Hangfire已启动。"); }
服务OnStart事件
protected override void OnStart(string[] args) { try { // 更新服务状态为启动中 ServiceStatus serviceStatus = new ServiceStatus { dwCurrentState = ServiceState.SERVICE_START_PENDING, dwWaitHint = 100000 }; SetServiceStatus(this.ServiceHandle, ref serviceStatus); // 信息日志 _logger.LogInformation("正在启动Windows Service 'BatchService'"); SetPolling(); StartHangfire(); _logger.LogInformation("Windows Service 'BatchService'已启动"); // 更新服务状态为运行中 serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; SetServiceStatus(this.ServiceHandle, ref serviceStatus); } catch (Exception e) { _logger.LogError($"Windows Service 'BatchService'启动失败 ({e})"); throw; } }
错误日志
2022-11-23 19:05:53.0881|DEBUG|Hangfire.Server.DelayedJobScheduler|已处理2个调度任务。
2022-11-23 19:05:53.1353|WARN|Hangfire.AutomaticRetryAttribute|处理任务'17'失败:发生异常。第5次重试(共10次)将在00:05:36后执行。|System.MissingMethodException: 未为此对象定义无参数构造函数。
在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
在 System.Activator.CreateInstance(Type type)
在 Hangfire.JobActivator.ActivateJob(Type jobType)
在 Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type)
在 Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
在 Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_0.b__0()
在 Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) 在 Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_1.<PerformJobWithFilters>b__2() 在 Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable1 filters)
在 Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
在 Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)
2022-11-23 19:05:53.1383|WARN|Hangfire.AutomaticRetryAttribute|处理任务'20'失败:发生异常。第2次重试(共10次)将在00:01:04后执行。|System.MissingMethodException: 无法创建接口的实例。
在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
在 System.Activator.CreateInstance(Type type)
在 Hangfire.JobActivator.ActivateJob(Type jobType)
在 Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type)
在 Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
在 Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_0.b__0()
在 Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) 在 Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_1.<PerformJobWithFilters>b__2() 在 Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable1 filters)
在 Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
在 Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)
问题
已通过搜索了解到该错误与Hangfire解析任务方法依赖的方式有关,但调整后仍未解决,请问接下来可以尝试哪些方案?
环境信息:OS:Windows Server 2016;.NET版本:4.6.1
内容的提问来源于stack exchange,提问作者Fysicus

