本文介绍了如何在C#中使用JobStorage获取所有Hangfire作业的列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Hangfire BackgroundJob在C#中使用以下代码创建后台作业。

var options = new BackgroundJobServerOptions
        {
            ServerName = "Test Server",
            SchedulePollingInterval = TimeSpan.FromSeconds(30),
            Queues = new[] { "critical", "default", "low" },
            Activator = new AutofacJobActivator(container),
        };
        var jobStorage = new MongoStorage("mongodb://localhost:*****", "TestDB", new MongoStorageOptions()
        {
            QueuePollInterval = TimeSpan.FromSeconds(30)                
        });
        var _Server = new BackgroundJobServer(options, jobStorage);

它将创建J观察者对象,之后,我将按如下方式创建调度和循环作业。

var InitJob = BackgroundJob.Schedule<TestInitializationJob>(job => job.Execute(), TimeSpan.FromSeconds(5));
        var secondJob = BackgroundJob.ContinueWith<Test_SecondJob>(InitJob, job => job.Execute());
        BackgroundJob.ContinueWith<Third_Job>(secondJob, job => job.Execute());
        RecurringJob.AddOrUpdate<RecurringJobInit>("test-recurring-job", job => job.Execute(), Cron.MinuteInterval(1));
之后,当我的应用程序停止或关闭时,我想删除或停止所有作业。因此,在我应用程序的OnStop事件中,我编写了以下代码。

var monitoringApi = JobStorage.Current.GetMonitoringApi();
                    var queues = monitoringApi.Queues();// BUT this is not returning all queues and all jobs
                    foreach (QueueWithTopEnqueuedJobsDto queue in queues)
                    {
                        var jobList  = monitoringApi.EnqueuedJobs(queue.Name, 0, 100);
                        foreach (var item in jobList)
                        {
                            BackgroundJob.Delete(item.Key);
                        }
                    }

但是,上面用于获取所有作业和所有队列的代码不起作用。它始终返回"default"队列,而不返回所有作业。

有人能想到使用HangfireJobStorage获取所有作业并在应用程序停止时停止这些作业吗?

如有任何帮助,不胜感激!

谢谢

推荐答案

单服务器安装

要获取所有重复作业,您可以使用作业存储(例如,通过静态实例或DI):

using (var connection = JobStorage.Current.GetConnection())
{
  var recurringJobs = connection.GetRecurringJobs();
  foreach (var recurringJob in recurringJobs)
  {
    if (NonRemovableJobs.ContainsKey(recurringJob.Id)) continue;
    logger.LogWarning($"Removing job with id [{recurringJob.Id}]");
    jobManager.RemoveIfExists(recurringJob.Id);
  }
}

如果您的应用程序充当单个Hangfire服务器,则应用程序一停止,所有作业处理都将停止。在这种情况下,甚至不需要移除它们。

多服务器设置

在对多个服务器使用相同的Hangfire表的多实例设置中,您会遇到这样一个问题,即并非所有应用程序都有可用的所有程序集。使用上面的方法,Hangfire会尝试反序列化它找到的每个作业,这会导致";程序集找不到&q;异常。

为了防止出现这种情况,我使用了以下变通方法,从表‘Hash’中加载列‘key’。它的格式为‘Recurning-Jobs:{YourJobIdentifier}’。如果需要,则使用作业ID删除作业:

var queue = 'MyInstanceQueue'; // probably using queues in a multi server setup
var recurringJobsRaw = await dbContext.HangfireHashes.FromSqlInterpolated($"SELECT [Key] FROM [Hangfire].[Hash] where Field='Queue' AND Value='{queue}'").ToListAsync();
var recJobIds = recurringJobsRaw.Select(s => s.Key.Split(":").Last());
foreach (var id in recJobIds)
{
  if (NonRemovableJobs.ContainsKey(id)) continue;
  logger.LogWarning($"Removing job with id [{id}]");
  jobManager.RemoveIfExists(id);
}

备注:为了使其与EF Core一起工作,我对Hangfire.Hash表使用了Keyless entity

这篇关于如何在C#中使用JobStorage获取所有Hangfire作业的列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 18:02