即使只安排了一次,我的工作也会执行任意次数

时间:2018-02-21 11:09:23

标签: c# jobs job-scheduling hangfire

  • Hangfire 1.6.17
  • SQL Server 2016(13.0.4206.0)

我有一个C#控制台应用程序,它使用OWIN来托管Hangfire服务器,如下所示:

public class Startup
{
    public void Configuration(IAppBuilder aAppBuilder)
    {
        //How we want to use Hangfire
        GlobalConfiguration.Configuration
                           .UseSqlServerStorage("HangfireConnectionString")
                           .UseConsole(new ConsoleOptions
                                       {
                                           BackgroundColor = "#0d3163",
                                           TextColor = "#ffffff",
                                           TimestampColor = "#00aad7"
                                       });

        //Read the settings file
        SettingsIni iniSettings = new SettingsIni(GeneralHelper.GetAppPath() + "settings.ini");

        //Dashboard
        aAppBuilder.UseHangfireDashboard(iniSettings.HttpServer.Path, new DashboardOptions
                                                                      {
                                                                          AppPath = "/",
                                                                          Authorization = new[]
                                                                                          {
                                                                                              new HangfireAuthorizationFilter()
                                                                                          }
                                                                      });

        //Server
        BackgroundJobServerOptions serverOptions = new BackgroundJobServerOptions
                                                   {
                                                       Queues = GeneralHelper.GetQueueNames(iniSettings).ToArray()
                                                   };

        aAppBuilder.UseHangfireServer(serverOptions);

        //Ensure our recurring tasks are running if required.
        if (iniSettings.Behaviour.DoPlatformManagerInit) TpHangfireJobsManager.Initialise();
    }
}

作为应用程序启动的一部分,我添加了一个火,忘了工作如下:

BackgroundJob.Enqueue<TpHardLinkAttachmentsForEmailMessagesWatchDog>(aX => aX.ExecuteJob(null, new TpHardLinkAttachmentsForEmailMessagesWatchDogParamsInput
                                                {
                                                    ForYear = 2017
                                                }));

并且正在执行的方法是:

public override void ExecuteJob(PerformContext aContext, TpHardLinkAttachmentsForEmailMessagesWatchDogParamsInput aParams)
{
    Trace.WriteLine($"Params: {aParams.ForYear}");
    DateTime startDate = new DateTime(aParams.ForYear, 1, 1);
    DateTime endDate = new DateTime(aParams.ForYear, 1, 31);

    //Start with a huge record id so we can work backwards
    long currRecId = int.MaxValue;

    //Keep getting records until we are done
    while (true)
    {


        //Find all records that have to be processed. We start with the highest record id in the year and then work backwards until we run out of record
        long idLast = currRecId;
        Trace.WriteLine($"Id Last: {idLast}");
        List<EmailActivityTableModel> recordsToProcess = _EmailActivityDomainService.GetWhere(
                                                                                        aR => aR.Id < idLast &&
                                                                                              aR.Created >= startDate &&
                                                                                              aR.Created <= endDate &&
                                                                                              (
                                                                                                  aR.ExternalIdKind == ExternalIdKindEnum.Family ||
                                                                                                  aR.ExternalIdKind == ExternalIdKindEnum.Individual
                                                                                              ) &&
                                                                                              (
                                                                                                  aR.ExternalId != "" ||
                                                                                                  aR.ExternalId != "-1"
                                                                                              ) //Ensure we have an external identifier
                                                                                    ).OrderByDescending(aR => aR.Id)
                                                                                    .Take(5).ToList();

        //We are done if we did not find any records
        if (recordsToProcess.Count == 0)
            break;

        aContext.WriteLine("Process {0} records.", recordsToProcess.Count);
        Trace.WriteLine($"Record Count: {recordsToProcess.Count}");

        foreach (EmailActivityTableModel emailActivityRecord in recordsToProcess)
        {
            aContext.WriteLine(emailActivityRecord.Id);

            currRecId = emailActivityRecord.Id;
            Trace.WriteLine($"Curr Rec Id: {emailActivityRecord.Id}");
        }

        //TESTING - Bail after the first iteration so 5 records
        return;
    }
}

所有方法所做的最终都是从数据库中读取一些记录并输出主键。我所看到的是该方法被多次调用(数量因控制台应用程序的每次运行而异),我看到以下内容:

enter image description here

我只看到HangFire中的一个成功任务:

enter image description here

我正在无异常(注意每次都完成所有5次迭代),因此作业不会因此重新启动。

所以我的问题是为什么我的ExecuteJob()会被多次调用?

1 个答案:

答案 0 :(得分:0)

我正在回答这个问题的完整性。

事实证明我得到了一个异常位,它没有显示在我的日志中。我最终通过添加coloured console logger来跟踪它。

我正在使用名为HangFire.Console的第三方软件包,该软件包的属性 DisableConcurrentExecution 存在详细问题here。交换 Mutex 的属性,现在一切都很好。