Search code examples
c#asp.nethangfire

HangFire recurring jobs on asp.net


I started using HangFire to process a task every X minutes/hours and I need to add recurring jobs. In console application I managed to do it just fine but on asp.net I can only get it to work once, through the BackgroundJob.Enqueue method.

public class Global : HttpApplication
{
    private static string LigacaoBD = myConn;
    private static ApiMethods sportRadar = new ApiMethods();
    private static Jogo jogo = new Jogo(LigacaoBD);
    private static List<SportRadar.ClassesCliente.Jogo> jogos;
    private static List<SportRadar.ClassesCliente.Competicao> competicoes;

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        GlobalConfiguration.Configuration.UseSqlServerStorage(LigacaoBD);

        using (var connection = JobStorage.Current.GetConnection())
        {
            foreach (var recurringJob in connection.GetRecurringJobs())
            {
                RecurringJob.RemoveIfExists(recurringJob.Id);
            }
        }

        using (var server = new BackgroundJobServer())
        {
            // This works just fine
            var id=BackgroundJob.Enqueue(() => Actualizacoes());
            // This does not.
            // I even checked the DB for job queue or something but couldn't find anything
            RecurringJob.AddOrUpdate(id, () => Actualizacoes(), Cron.Minutely);
        }
    }



    public void Actualizacoes()
    {
        // Stuff I need to do regularly
    }
}

I thought I got it right but evidently I got something wrong here. Where do you think the problem might be at?


Solution

  • There's two problems.

    One. because you're passing id in - which is unnecessary in your implementation.

    BackgroundJob.Enqueue returns a unique identifier for a job. In your code, this job has already been queued and executed.

    Change

    RecurringJob.AddOrUpdate(id, () => Actualizacoes(), Cron.Minutely);
    

    to

    RecurringJob.AddOrUpdate(() => Actualizacoes(), Cron.Minutely);
    

    Also, you're wrapping the creation of BackgroundJobServer in a using statement. Then creating the job in there. Therefore, the BackgroundJobServer is being cleared up by GC.

    Instead, try this:

    public class Global : HttpApplication
    {
        private static string LigacaoBD = myConn;
        private static ApiMethods sportRadar = new ApiMethods();
        private static Jogo jogo = new Jogo(LigacaoBD);
        private static List<SportRadar.ClassesCliente.Jogo> jogos;
        private static List<SportRadar.ClassesCliente.Competicao> competicoes;
    
        private BackgroundJobServer _backgroundJobServer;
    
        void Application_Start(object sender, EventArgs e)
        {
            // Code that runs on application startup
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
    
            GlobalConfiguration.Configuration.UseSqlServerStorage(LigacaoBD);
    
            using (var connection = JobStorage.Current.GetConnection())
            {
                foreach (var recurringJob in connection.GetRecurringJobs())
                {
                    RecurringJob.RemoveIfExists(recurringJob.Id);
                }
            }
    
            //create an instance of BackgroundJobServer
            _backgroundJobServer = new BackgroundJobServer();
    
            //add your recurring job
            RecurringJob.AddOrUpdate(() => Actualizacoes(), Cron.Minutely);
        }
    }