【问题标题】:Hangfire recurring job to call method is Startup using existing servicesHangfire 循环作业调用方法是使用现有服务启动
【发布时间】:2021-11-10 04:25:27
【问题描述】:

我正在尝试设置 Hangfire 以使用独立方法在 Startup.cs 内运行重复作业。为此,我需要获取一些我已经注入的 ApplicationServices。但作业执行失败并出现此错误:

Recurring job 'Job: Dispatch Email from Queue' can't be scheduled due to an error and will be retried in 00:00:15.
System.InvalidOperationException: Recurring job can't be scheduled, see inner exception for details.
 ---> Hangfire.Common.JobLoadException: Could not load the job. See inner exception for the details.
 ---> Newtonsoft.Json.JsonSerializationException: Could not create an instance of type DA.BrrMs.Application.Interfaces.ServiceInterfaces.IBudgetReleaseRequestService. Type is an interface or abstract class and cannot be instantiated.

这是我所拥有的:

public class Startup
{
    private IConfiguration Configuration { get; }

     private RecurringJobManager _jobManager;

    public Startup(IConfiguration configuration) => Configuration = configuration;

    public void ConfigureServices(IServiceCollection services)
    {
        ...

        if (Configuration["SystemSettings:UseHangfire"] == "1")
        {
            services.AddHangfire(c => c.UseMemoryStorage());
            JobStorage.Current = new MemoryStorage();
            services.AddHangfireServer();
            GlobalConfiguration.Configuration.UseMemoryStorage();
        }

        RegisterServices(services);
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...

        var requestService = app.ApplicationServices.GetService<IBudgetReleaseRequestService>();
        var mailService    = app.ApplicationServices.GetService<IMailer>();

        _jobManager = new RecurringJobManager();
        _jobManager.AddOrUpdate("Job: Dispatch Email from Queue", () => StartupMailJob(requestService, mailService), Cron.Minutely);
    }

    private static void RegisterServices(IServiceCollection services) => DependencyContainer.RegisterServices(services);

    public static async Task StartupMailJob(IBudgetReleaseRequestService requestService, IMailer mailService)
    {
        try
        {
            var emailsToSend = await requestService.DispatchEmails();

            // Send emails
            foreach (var emailToSend in emailsToSend)
            {

            }

            // Update status of sent                
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

}

// In a project, far far away...

public static void RegisterServices(IServiceCollection services)
{
    ...
    services.AddScoped<IBudgetReleaseRequestService, BudgetReleaseRequestService>();
    ...
}

如何满足Hangfire对类实例而不是接口的要求?

【问题讨论】:

    标签: c# asp.net-core-webapi ioc-container .net-6.0


    【解决方案1】:

    这是我发现最适合我的实现:

    1在 Startup.cs 中注册我要调度的服务

     services.AddScoped<IMyJob, MYJob>();
    

    2创建了一个激活器类,用于定义作业执行的范围。

    public class HangFireActivatorMyJob : IHangFireActivatorMyJob
    {
        private readonly IServiceProvider _serviceProvider;
    
        public HangFireActivatorMyJob (IServiceProvider serviceProvider)
        {
            this._serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
        }
    
        public async Task Run(IJobCancellationToken token)
        {
            token.ThrowIfCancellationRequested();
            await RunAtTimeOf(DateTime.Now);
        }
    
        public async Task RunAtTimeOf(DateTime now)
        {
            using IServiceScope scope = this._serviceProvider.CreateScope();
            var myJobService= scope.ServiceProvider.GetRequiredService<IMyJob>);
            await myJobService.RunSomeTaskOnJob();
        }
    }
    

    3注册激活器

    services.AddTransient<IHangFireActivatorMyJob, HangFireActivatorMyJob >();
    

    4在Startup.cs中的configure方法中添加IRecurringJobManager接口

     public void Configure(
          IApplicationBuilder app,
          IWebHostEnvironment env,
          IRecurringJobManager recurringJobManager)
    

    5 将作业添加到提供的 IRecurringJobManager

    recurringJobManager.AddOrUpdate<HangFireActivatorMyJob >(nameof(HangFireActivatorMyJob ),
                    job => serviceProvider.GetRequiredService<IHangFireActivatorMyJob>()
                        .Run(JobCancellationToken.Null)
                    , Cron.Hourly(3), TimeZoneInfo.Utc);
    

    【讨论】:

      猜你喜欢
      • 2022-11-15
      • 2019-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多