Learn how to schedule tasks with HangFire in Asp.Net Core

What are Background Jobs?
In general, background tasks are tasks that the program must perform automatically at specified times, for example:

Ruhollah Jafari
12 min readMay 14, 2021

Consider a situation where you have a method with a large volume of complex calculations that starts when the user submits their request and the current user has no choice but to wait, but if this was calculated at another time before the user's request and only the result It was displayed to the user that it was definitely a better decision than the instantaneous calculation of that method at the time of the user's request.

In another scenario, imagine that you want to email a summary of your website content to website users at a specific time each night. Automatically done by the program.

Also, conditions such as sending an authentication email one hour after registration, backing up program data on a weekly basis, and so on are all in the Background Job category of a program.

Question: What is HangFire?

As you know, background tasks require a time management system to get things done on time. HangFire is an open source package for scheduling tasks and will do it the easiest way.

HangFire, along with Quartz, another scheduling system, is also one of the most popular packages for scheduling background tasks, and we’ll look at the pros and cons of the two below.

Compare HangFire and Quartz:

It can be said that these two packages are very similar to each other and their main difference in the underlying layers and the type of calculations when each lies that they have their own algorithm for this calculation but eventually do the same thing.

database :

The difference that can be mentioned is the presence of the Redis Store feature in HangFire, which Quratz did not offer such a feature on its own, and to use Redis in Quartz, you must personally configure the two together. The Redis database offers higher speed and performance due to its database structure, which is quite evident in projects with a large number of tasks and records. Of course, this feature is not free in HangFire, and to have it from HangFire, you need to pay for it, but if you do not want to pay for it and still use it, an open source package has been designed for it, which you can see from the link below. do.

Structure :

The HangFire package was originally developed with .NET and .NET architectures, but Quartz was originally written for Java and was a kind of release language for .NET, which naturally had its effects, and some architectures and The Java thinking is obvious, which of course does not pose a problem and has no limitations on HangFire in terms of functionality. Is.

Dashboard :

Both packages support the dashboard, which you can use to manage tasks created in this dashboard and a dedicated ui designed to display tasks. The HangFire dashboard comes with it by default, which after installing HangFire you can easily see the dashboard mounted on it, but in Quartz, the dashboard must be added as an extension in a separate package and used. In the link below you can see two of the best dashboards for Quartz that you can use if needed.

Using HangFire:
1. Installation:
To install HangFire in the Asp.Net Core project, you first need to install the required packages, which include:

Install-Package Hangfire.Core

Install-Package Hangfire.SqlServer

Install-Package Hangfire.AspNetCore

After installing the packages, we need to apply the settings required to implement HangFire in the program. These settings include adding HangFire services and interfaces to the application, which we will do by adding HangFire to the ConfigureService method of the Startup class:

The HangFire package has tables for managing work and time, which are placed on your application database after installation. You just have to be careful to set your ConnectionString database in the AddHangFire method to recognize the application database and the desired tables. Add a new schema called HangFire.

HangFire connects to the SqlServer database by default.

This package has a dedicated dashboard in which it provides us with a list of the types of tasks in the queue and a report of what has been done. To configure this dashboard, you need to add its related middleware and a new endpoint to identify the path of the HangFire dashboard in the program in the Configure method of the Startup class:

Of course, you can customize the HangFire dashboard address in the app from the word “hangfire” to anything you want. To do this, simply define a new HangFire address in the defined middleware as string input.

app.UseHangfireDashboard("/mydashboard");http://localhost:50255/mydashboard

2. Dashboard:
The HangFire dashboard consists of several sections and tabs, each of which we will briefly review.

Job tab:

All defined tasks including Enqueued, Succeeded, Processing, Failed, etc. are shown in this tab.

Retries tab:

This tab is related to the tasks that failed in the scheduling and execution routine for various reasons such as the program being stopped by iis or the server down or any other external factor and were not executed in the specified schedule. It also gives us the ability to restart the desired job, which allows us to manage lost tasks and do them again.

Recurring Jobs tab:

When you define a task such as backing up a database on a monthly basis and it is supposed to happen every month, it is considered a duplicate task and this tab is responsible for displaying such tasks.

Servers tab:

This section shows the services that HangFire uses to calculate scheduling. When you add the services.AddHangfireServer method to the ConfigureService method of the Startup class, HangFire services are activated to calculate schedules.

3. Dashboard security:

As you know, the dashboard provides us with complete information about the type of work and its execution time and the names of the methods, as well as allowing changes such as deleting a task or re-executing tasks or quickly executing untimely tasks. Gives the user. Sometimes this information may contain security and non-public content that not everyone in the app has access to. To manage this, you can follow the steps below:

Step 1: Create a class (for example called MyAuthorizationFilter) that will inherit from the interface called IDashboardAuthorizationFilter.

Within this class, a method called Authorize is implemented from the corresponding interface that controls the authentication conditions and whether or not to grant access. This method has a Boolian output that returns false output if any of your authentication conditions are not verified. In this example we have applied the login restriction for access, which we get from HttpContext.

Step 2: In this step, we add the class that we have created as an authentication filter for users in the middleware options of the HangFire package.

Another option of this middleware that can be used to control access in HangFire is called Read-only view option.

This option removes any change in the task process from the dashboard screen from any user and uses the dashboard only to display tasks and nothing else.

Types of tasks in HangFire:

1. Fire-And-Forget Tasks:

Fire-And-Forget tasks do not have a specific schedule and are executed immediately after the call. For example, consider the situation where you want to send a welcome email after each user registers on the website. This is considered a background task, but you do not want to set a specific schedule for it. In such cases, you can use the Enqueue method and create a Fire-And-Forget task so that this task is named only in your background tasks. Be visible.

As you can see in the example above, to use the Fire-and-Forget tasks in HangFire, we first need to inject the IBackgroundJobClient interface and use the Enqueue method in this interface to create a background task that calls the SendWelcomeMail method.

2. Delayed tasks:

As the name implies, Delayed tasks are tasks that will be executed with a delay in time. In general, the timing of these tasks is divided into two categories:

The first category: run after a delay in a specified time.
Consider the same conditions for sending emails to users who register on your website, but this time you want to send a welcome email not immediately but 10 minutes after the user registers. In this type you want a 10 minute delay that Delayed Jobs do for us.

In this example, using the Schedule method in the IBackgroundJobClient interface, we were able to call the SendWelcomeMail method and apply a 10-minute delay to the HangFire method with the TimeSpan input.

You can also use other TimeSpan inputs including TimeSpan.FromMilliseconds and TimeSpan.FromSeconds and TimeSpan.FromMinutes and TimeSpan.FromDays to set latency in your tasks.

The second category: run at a specific time.

Another way to use the Schedule method is to set a specific date and time for the execution of tasks on that single date and time. For example, consider a scenario where the execution and scheduling command is available to the user and the user wants to send a Reminder on a specific date, in which case you can use another instance of the Schedule method that receives input of DateTimeOffset. Select a specific date to run.

In this example, we have received a specific date for the execution of our tasks from the user in the action input and pass it to the Schedule method in the defined DateTimeOffset.

3. Recurring Tasks:

Recurring tasks are tasks that must be performed in a rotating period of time. We will get acquainted with it in a further example. Suppose you want the program to back up existing database information every week. Here you have a task that is going to be repeated every week and every time.

To set up a Recurring Job, you must inject another interface called IRecurringJobManager and use the AddOrUpdate method. At the input of this method, a material defined in HangFire called Cron is received, which receives the time cycle, which is here on a weekly basis.

Other types of Cron include:

Every minute (Cron.Minutely):
This Cron will run every minute.

_recurringJobManager.AddOrUpdate("test", () => job , Cron.Minutely);

Every hour (Cron.Hourly):
This Cron runs once an hour by default in the first minute of each hour.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Hourly);

But you can give it a minute input, in which case it will run in the N minute of each hour.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Hourly(10));

Every day (Cron.Daily):
This Cron will be run daily and by default in the first hour and first minute of each day.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Daily);

Alternatively, you can give it hour and minute input to run at a specific time and minute each day.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Daily(3,10));

Weekly (Cron.Weekly):
This is a weekly Cron. By default it runs every Saturday in the first hour and in the first minute.

_recurringJobManager.AddOrUpdate("test", () => Job,Cron.Weekly(DayOfWeek.Monday,3,10));

Every month (Cron.Monthly):
This Cron applies its monthly schedule on the first day of the month in the first hour of the day and in the first minute of the hour.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Monthly);

And if you give input, you can also set its schedule on the few days of the month at what time and minute.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Monthly(10,3,10));

Every year (Cron.Yearly):
And finally, this Cron will do its job annually in the first month, day, hour and minute of each year.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Yearly);

This, like the rest, receives inputs that include month, day, hour and minute, respectively.

_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Yearly(2,4,3,10));

Finally, using these crowns, you can create different types of Recurring Jobs.

4. Continuations tasks:

These types of tasks are dependent on other tasks and are generally used when we want to run one task after another with a timeline relative to the execution time of the first task. For example, we want to send an authentication email to the user 10 minutes after registration, which we did similarly in the Delayed tasks. But we also intend to cancel the authentication of the sent link 5 minutes after sending the email. In this scenario we have two schedules, the first 10 minutes after user registration and the second 5 minutes after running the first method.

Some HangFire Tips and Tricks:

1. Using Cron Expression in Recurring Jobs:

Crones are generally a defined structure for determining time intervals. Cron stands for Command Run On, which refers to the execution of a command at a specific time. To use it, we first define this structure:

We explain this structure from bottom to top below:

* * * * *
First field (Minute): In this field, you must enter a specific minute of an hour, such as 10 minutes (you can also specify the range)
Second field (Hour): In this field, you must enter the specified time in clock format. Like 7 o’clock (you can also specify the range), such as 7–12 o’clock
Day 3 Month: In this field you must enter a day of the month, such as the 15th day of the month (you can also specify the range)
Fourth field (Month): In this field you must enter a month of the year, for example the 4th month (April) (you can also specify the range)
Fifth field (Day of Week): In this field, you must specify a day of the week or a range of those days, such as the zero of the week, which in European and American countries is equivalent to Sunday.
As you can see, Crones offer better access to different time intervals that you can use in Recurring methods instead of Yearly — Monthly — Weekly — Daily — Hourly — Minutly inputs. In fact, these inputs themselves are a method defined in the Cron class, which by calling it creates a Cron Expression output and is placed inside the input of the Recurring method.

We will give an example below to better understand the need for Cron Expressions. Suppose you want to have a schedule that runs “every month between the 10th and 15th, at 4:00 a.m. daily.” It is not possible to apply this scheduler with the usual methods in the Cron class, but you can apply it with Cron Expression, which will look like this:

0 4 10–15 * *
There are websites for building Cron Expressions that help us design complex types of Cron Expressions and use them to create more accurate and detailed schedules. One of the best websites to do this is crontab.guru.

To use Cron Expression in Recurring methods, instead of Yearly — Monthly — Weekly — Daily — Hourly — Minutly inputs, define Cron Expression itself in the method input:

_recurringJobManager.AddOrUpdate("test", () => job , "0 4 10-15 * *" );

2. Trigger method:

The Trigger method is a method for instant execution of recurring tasks, with the help of which you can execute this type of task at any time, regardless of its schedule, and of course, it has no effect on the next repetition.

RecurringJob.Trigger("some-id");

3. Determine the expiration date for Recurring Jobs:

Sometimes there may be situations in Recurring tasks where you assume you want to do something every month, but this repetition ends at the end of the year. In this case, we have to set an Expire Time for our Recurring method to end after 12 months of repetition on 140X / 12/30. HangFire does not define input for Recurring methods as ExpireTime, but can be defined as an ExpireTime by creating a Schedule to set a specific date for deleting the Recurring method.

Executing this first method creates a task to repeat in the monthly schedule, and in the second method specifies a time to delete the first method.

Finally, I hope this article has been useful to you. You can send me your feedback in the form of a comment or a coffee.

--

--

Ruhollah Jafari
Ruhollah Jafari

Written by Ruhollah Jafari

I am a Full Stack .Net developer with good experience in developing web applications using Asp.Net Frame Work And Core, Mvc , WebApi , JavaScript ,Sql Server ,

Responses (2)