How to Manage Background Jobs in .NET with Hangfire

Simplify Background Jobs in .NET with Hangfire
×
Mohit Borse
Lead Engineer
Mohit has been working on .NET, React, Angular, TypeScript, VS-Code, and Visual Studio 2019 for development. He has trouble-shot and fixed probl... Read More

With the increasing complexity of software and web applications, automating recurring tasks has never been more essential. Whether it’s data maintenance activities like database cleanup, archiving, and backups, or user management tasks such as account expirations and password reset notifications—automating these processes can significantly enhance efficiency. Here, tools like the Hangfire .NET library make it easier to manage these background processes. These are essential for ensuring smooth functionality, maintenance, and overall user experience.

Consider the need to auto-cancel incidents stuck in a “pending” state for 5 days. Such tasks require precise scheduling and minimal system load during peak hours. Traditionally, Windows Services were used for background jobs, but they were often cumbersome to manage.

To overcome this, I chose the Hangfire .NET library, which simplifies the creation and management of background tasks without relying on Windows Services. Thus, it offers a more efficient solution for modern applications.

collatral

Learn about the key features of Node.js, Java, and .NET and how they can drive your business forward.

Let’s further delve into its concept, features, and architecture in detail. As you read on, you’ll also discover how to seamlessly integrate Hangfire into .NET applications.

What is Hangfire and Why does it matter?

Hangfire is an open-source .NET library that provides a wrapper on your code and an easy way to perform the background jobs. So, the end-user doesn’t require to wait for the step-by-step process. Hangfire can handle your calls and act, so you don’t have to worry about the work.

It creates background jobs and stores them in reliable storage options like SQL Server, Redis, MySQL, and others. It allows you to securely restart your application while seamlessly working with .NET, without worrying about application pool recycling.

It also provides a dashboard to track your queued jobs and lets you enqueue a job in your code to run asynchronously in a first-come, first-serve order.

Here are some key features of Hangfire that make it an efficient solution:

  • Open-source .NET library: Hangfire is a free, open-source library built specifically for .NET applications, supported and continuously improved by the global developer community. This community-driven nature ensures it stays up to date with the latest advancements and best practices.
  • Easy to configure: It offers a seamless integration process, allowing you to effortlessly add it to your existing .NET projects. The configuration is straightforward, ensuring minimal setup time and enabling you to focus more on developing your application rather than dealing with complex installation procedures.
  • No need for Windows services: Unlike traditional solutions that require setting up separate applications or Windows services to run background tasks, Hangfire simplifies this by handling everything within the .NET application itself. This eliminates the overhead of managing additional services, streamlining your development process.
  • Persistent jobs: It ensures that all jobs, including their state and progress, are stored in a reliable database. This persistence guarantees that even in the event of a system failure or restart, your background tasks are not lost and can resume from where they are left off, ensuring complete reliability.
  • Automatic job retries: It takes the burden off developers by automatically retrying failed jobs. This built-in feature ensures that background tasks are not left incomplete, reducing the need for manual intervention and improving the overall reliability and efficiency of job execution.
  • User-friendly dashboard: The platform comes with a clean, intuitive dashboard that simplifies job monitoring and management. Its user-centric design allows developers to quickly grasp the status of tasks and take necessary actions with minimal effort.
  • Distributed and Self-Maintainable: It supports distributed processing, enabling background tasks to be processed across multiple servers or machines. It is also self-maintainable. This quality reduces the need for manual intervention and ensures tasks run smoothly in complex environments.
  • Simplified Background Job Processing: With Hangfire, developers can easily create, schedule, and execute background jobs with minimal configuration. This streamlined process eliminates the complexity often associated with background job management in traditional systems.
  • Easy Monitoring and Management: It offers powerful tools to track and manage the lifecycle of jobs effortlessly. With real-time monitoring, you can quickly identify any issues and maintain full control over your background tasks.

Now that you know the definition and purpose, further learn about Hangfire’s architecture.

How does Hangfire’s architecture work?

Here’s how the Hangfire architecture looks:

architecture-of-hangfire

Fig: Architecture of Hangfire

In the above image, here’s what happens:

  • The Hangfire client creates a job and stores it in job storage.
  • Next, the Hangfire server retrieves jobs from the storage.
  • It processes the jobs in the background.
  • After completing the tasks, the server updates the job status in the storage.

Extra note: Using Hangfire, we can create the following types of background jobs:

  1. Fire and forget
  2. Delayed jobs
  3. Recurring jobs (similar to Cron jobs)
  4. Continuation jobs
  5. Batch jobs (available in the Pro version)
  6. Batch continues (available in the Pro Version)

Up next, discover how to seamlessly integrate Hangfire into your .NET applications!

Extra note: Learn about advanced application development.

How to Configure and Integrate Hangfire in .NET Apps?

Here are the steps that you need to follow to integrate Hangfire in .NET applications:

Step 1: First, install these packages in your .NET application:

  • Hangfire
  • Hangfire.Core
  • Hangfire.AspNetCore
  • Hangfire.SqlServer

You can install all dependency packages from the NuGet package manager as shown in this screenshot:

nuget-package

Step 2: Next, register Hangfire as a service in the start-up file.

To do this, open the Startup.cs class and locate a ConfigureServices method. Then add the code below to the configured database connection.

Make sure to include the necessary imports:

using Hangfire;

using Hangfire.SqlServer;

Then add the following code in the ConfigureServices method:

configuration-1

If you’re curious about the SqlServerStorageOptions mentioned above, here’s a brief explanation of each:

  • CommandBatchMaxTimeout = TimeSpan.FromMinutes(5): Sets the maximum time (5 minutes in this case) that Hangfire will wait for a batch of database commands to be executed. If a command takes longer, it will be considered failed, and Hangfire might retry it.
  • SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5): Defines the period of inactivity (5 minutes in this case). After this, Hangfire considers a server worker “invisible” and removes it from the worker pool. This helps prevent stale worker information from lingering in the database.
  • QueuePollInterval = TimeSpan.Zero: Sets the interval between checks for new jobs in the queue. By setting it to TimeSpan.Zero (no interval), Hangfire constantly polls the queue for new jobs, providing minimal delay in job execution. However, this can increase database load. Consider a small non-zero value for production environments.
  • UseRecommendedIsolationLevel = true: Instructs Hangfire to use the recommended transaction isolation level for database operations. This can help to avoid data consistency issues but may have a slight performance impact.
  • DisableGlobalLocks = true (Requires Schema 7 Migration): Disables global locks acquired by Hangfire during certain operations. This can improve performance in high concurrency scenarios but requires your SQL Server schema to be upgraded to version 7 (migration might be necessary).
  • PrepareSchemaIfNecessary = true: This instructs Hangfire to automatically create the necessary tables and other database objects within the specified schema (dbo in this case) if they don’t already exist. This is generally recommended for initial setup and deployments.
  • SchemaName = “dbo”: This explicitly specifies that Hangfire should use the dbo schema for all its database operations. If you have a different schema for Hangfire, change “dbo” to the appropriate schema name.

Step 3: Add the following line to register the Hangfire server:

services.AddHangfireServer();

Step 4: To configure the Hangfire Dashboard, you need to add the following code in the configure method of start-up class:

app.UseHangfireDashboard();

Now that you’re set with the above steps, before running the application, familiarize yourself with the key code syntaxes related to job implementation.

What Are the Code Syntaxes for Job Implementation?

Here are some of the important code syntaxes for job implementation:

a. Fire & Forget Job: Inject the IBackgroundJobClient into the desired class and use its Enqueue method to execute the job immediately, as shown below:

fire-forget-job

b. Delayed Job: A delayed job is executed only once, but after a specified time interval, rather than immediately. Refer to the following screenshot:

delayed-job

c. Simple Recurring Job: A recurring job requires the IRecurringJobManager and additional parameters such as jobName, action method, and a cron expression. Refer to the following screenshot:

recurring-job

Note:
1. The first parameter is the task ID, which must be unique. It is used for updating or deleting the job later.

remove-job

2. The second parameter represents the action which is executed at a specified time.

3. The third parameter is the cron expression, a compact way to define recurring schedules for tasks.

You might be wondering about cron expressions, right? Let me help break down the concept for you.

What is Cron Expression?

A cron expression is a string used to define the schedule for a cron job, which automates repetitive tasks. It consists of five fields, each representing a specific time value for when the task should run, such as:

cron-expression

For example, the cron expression */2 * * * * means “run every 2nd minute.”

Note: You can learn more about cron expressions by visiting Crontab Guru’s website.

If you set up a recurring job using the syntax below, it will run immediately today and start checking the cron expressions. The ExecuteDailyJob public method will be triggered when a cron expression matches. Here’s the syntax:

RecurringJob.AddOrUpdate(“MyJob”,() => ExecuteDailyJob(), “*/2 * * * *“);

Here are some of the parameters that RecurringJob.AddOrUpdate() methods accepts:

  • string recurringJobId
  • Expression<Action> methodCall
  • Func<string> cronExpression
  • TimeZoneInfo timeZone = null (optional)
  • string queue = “default” (optional)

Here’s a diagram illustrating what each element represents:

recurringjobaddorupdate

Hangfire can store all scheduled job data in a database. After configuring the database connection in the Startup.cs file, Hangfire automatically creates tables to manage job information.

The tables created are as follows:

  • AggregatedCounter
  • Counter
  • Hash
  • Job
  • JobParameter
  • JobQueue
  • List
  • Schema Server
  • Set
  • State

Now, we are moving onto the final step of running the application.

How to Run the Application?

Run the application and open the following URL (assuming your app is running on port 44312) to access the Hangfire Dashboard.

You’ll then see that the background job has been completed successfully.

https://localhost:44312/hangfire/

Here’s how the dashboard will look:

dashboard

The Hangfire Dashboard offers a variety of options to view jobs, servers, recurring jobs, and more. It also shows a list of jobs by their status, like this:

hangfire-jobs

recurring-job-syntax

When executing the above code, Hangfire will add entries to the [Hash] and [Set] tables, as given below:

a. [Hash] table:

hash-table

b. [Set] table:

set-table

Optional Step: Additionally, you can create a generic component in Angular that generates cron expressions for recurring jobs.

Here are the recurring schedule types:

recurring-daily-onetime

a. Daily: One Time: 16 22 * * *: This Cron expression schedules a job to run once every day at 10:16 PM.

  • 16: The minute (16th minute)
  • 22: The hour (10 PM)
  • * * *: Every day, every month, and every day of the week

b. Daily: After Every: 16-16 22-23 * * *: This expression schedules the job to run every day at 10:16 PM and 11:16 PM.

  • 16-16: The minute (16th minute, which means it runs only once per hour)
  • 22-23: The hour (runs at both 10 PM and 11 PM)
  • * * *: Every day, every month, and every day of the week

recurring-daily-after-every

That’s a wrap.

So, with Hangfire’s easy setup, intuitive dashboard, and robust job management features, it simplifies the automation process by eliminating the complexities typically associated with traditional solutions. Whether you need to schedule background tasks or manage recurring jobs, Hangfire offers a seamless experience. It is an experience that allows developers to focus on core functionality instead of dealing with task automation challenges.

Its flexibility and scalability make it an excellent choice for both small projects and enterprise-level applications. So, if you’re looking to streamline your workflow and boost productivity, I highly recommend you get started with Hangfire today!

Do you wish to learn more about cutting software development services and tech solutions? Reach us at Nitor Infotech.

subscribe image

Subscribe to our
fortnightly newsletter!

we'll keep you in the loop with everything that's trending in the tech world.

We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.