如何在类方法中触发hangfire而不向触发它发送请求

Posted

技术标签:

【中文标题】如何在类方法中触发hangfire而不向触发它发送请求【英文标题】:How to trigger hangfire in a class method without sending a request to the trigger it 【发布时间】:2022-01-14 10:40:46 【问题描述】:

我习惯用top-shelf写windows服务,windows服务运行时服务会自动触发。

我遇到了hangfire,我认为它很酷,并且开箱即用可以完成很多工作。但是循环作业不是在类方法中触发的。

我希望在应用程序启动几分钟后触发作业。

我看到的所有示例都有从控制器发送的请求以启动作业。

    public class ReportJobs
    
        private readonly IBackgroundJobClient _backgroundJobClient;
        private readonly IRecurringJobManager _recurringJobManager;
        private readonly Report report;

        public ReportJobs(Report _report, IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager)
        
            _backgroundJobClient = backgroundJobClient;
            _recurringJobManager = recurringJobManager;
            report = _report;
        

        public async Task<List<Report>> GetReportAsync() 
        

            var currentDate = DateTime.Now.ToString("MM-dd-yyyy");
            var future18Months = DateTime.Now.AddMonths(18).ToString("MM-dd-yyyy");

            var report = await report.GetReports(currentDate, future18Months);
            return report;
        

        public void ScheduleReport()
        
            RecurringJob.AddOrUpdate("jobId", () => GetReportAsync(), Cron.Minutely);
        
    

我从hangman docs 获得了这个启动设置 启动.cs

  // Add Hangfire services.
            services.AddHangfire(configuration => configuration
                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                .UseSimpleAssemblyNameTypeSerializer()
                .UseRecommendedSerializerSettings()
                .UseSqlServerStorage(Configuration.GetConnectionString("InfoConnection"), new SqlServerStorageOptions
                
                    CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                    SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                    QueuePollInterval = TimeSpan.Zero,
                    UseRecommendedIsolationLevel = true,
                    DisableGlobalLocks = true
                ));

            // Add the processing server as IHostedService
            services.AddHangfireServer();

如何在不发送请求的情况下使其正常工作,因为此作业必须每 4 天运行一次

【问题讨论】:

如果您希望它每 4 天发生一次,然后在应用程序启动时定义一个 recurring job。附带说明:it's difficult to get your ASP.NET app running 24/7 由于应用程序池关闭和空闲超时等原因。我们发现使用 TopShelf 在 Windows 服务中托管 Hangfire 比让作业执行成为 Web 应用程序的一部分要好得多。 【参考方案1】:

如果您希望它在应用启动时运行一次。我的建议是使用 IHostedService 'interface'。如果您在此处调用 RecurringJob,它将工作一次,并在您设置工作的时间结束时再次触发。

例子;

public static void Main(string[] args)

    var host = CreateHostBuilder(args).Build();

    host.Run();


private static IHostBuilder CreateHostBuilder(string[] args)

   var hostBuilder = Host.CreateDefaultBuilder(args).ConfigureServices((_, services) =>  services.AddHostedService<Worker>(); );

   return hostBuilder;



public class Worker : IHostedService

    private readonly IHostApplicationLifetime _appLifetime;

    private readonly IServiceProvider _serviceProdider;

    public Worker(IHostApplicationLifetime appLifetime,
        IServiceProvider serviceProvider)
    
        _appLifetime = appLifetime;
        _serviceProdider = serviceProvider;
    

    public async Task StartAsync(CancellationToken cancellationToken)
    
        _appLifetime.ApplicationStarted.Register(OnStarted);
        await Task.CompletedTask;
    

    public async Task StopAsync(CancellationToken cancellationToken)
    
        await Task.CompletedTask;
    

    private void OnStarted()
    
        using var iServiceScope = _serviceProdider.CreateScope();
        var layerHangFire = iServiceScope.ServiceProvider.GetRequiredService<IRecurringJobManager>();

    

【讨论】:

是的,这会起作用。但我已经实现了一些有效的方法【参考方案2】:

所以我添加了这个来配置启动中的方法。

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IRecurringJobManager recurringJobs)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Info v1"));
            


            app.UseHangfireDashboard("/hangfire");
            recurringJobs.AddOrUpdate("Job", Job.FromExpression<ReportJobs>(x => x.ScheduleReport()), "*/5 * * * *");

            app.UseHttpsRedirection();
            app.UseStaticFiles();

      

【讨论】:

以上是关于如何在类方法中触发hangfire而不向触发它发送请求的主要内容,如果未能解决你的问题,请参考以下文章

如何在 vue 中触发 npm 包内的方法?

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

libeventbufferevent 2

在不向撤消堆栈添加撤消命令的情况下更改 QTextEdit

在 Sencha Touch 中设置 numberfield 的值而不触发“change”事件

如何在视图内的特定位置触发 Android Lollipop 的涟漪效应,而不触发触摸事件?