{"id":239,"date":"2025-07-29T09:50:55","date_gmt":"2025-07-29T09:50:55","guid":{"rendered":"https:\/\/www.dotnetdevelopers.us\/blogs\/?p=239"},"modified":"2025-08-04T09:43:44","modified_gmt":"2025-08-04T09:43:44","slug":"scheduling-background-tasks","status":"publish","type":"post","link":"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/","title":{"rendered":"Scheduling Background Tasks in .NET with Hangfire"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_74 counter-hierarchy ez-toc-counter ez-toc-light-blue ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#What_is_Hangfire\" >What is Hangfire?<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Key_Features\" >Key Features:<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Why_Use_Hangfire\" >Why Use Hangfire?<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Setting_Up_Hangfire_in_a_NET_Application\" >Setting Up Hangfire in a .NET Application<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Step_1_Install_Hangfire_via_NuGet\" >Step 1: Install Hangfire via NuGet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Step_2_Configure_Hangfire_in_Startupcs_for_NET_Core\" >Step 2: Configure Hangfire in Startup.cs (for .NET Core)<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Types_of_Background_Jobs_in_Hangfire\" >Types of Background Jobs in Hangfire<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#1_Fire-and-Forget_Jobs\" >1. Fire-and-Forget Jobs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#2_Delayed_Jobs\" >2. Delayed Jobs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#3_Recurring_Jobs\" >3. Recurring Jobs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#4_Continuation_Jobs\" >4. Continuation Jobs<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Using_the_Hangfire_Dashboard\" >Using the Hangfire Dashboard<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Real-Life_Example_Sending_Emails_in_the_Background\" >Real-Life Example: Sending Emails in the Background<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Step_1_Create_the_Job_Method\" >Step 1: Create the Job Method<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Step_2_Enqueue_the_Job\" >Step 2: Enqueue the Job<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Best_Practices_for_Using_Hangfire\" >Best Practices for Using Hangfire<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Error_Handling_and_Retries\" >Error Handling and Retries<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Advanced_Features_You_Should_Know\" >Advanced Features You Should Know<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Q1_Is_Hangfire_free_to_use\" >Q1:  Is Hangfire free to use?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Q2_Can_I_use_Hangfire_with_NET_6\" >Q2: Can I use Hangfire with .NET 6+?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Q3_Where_are_the_jobs_stored\" >Q3: Where are the jobs stored?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Q4_What_happens_if_the_server_crashes\" >Q4: What happens if the server crashes?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/www.dotnetdevelopers.us\/blogs\/scheduling-background-tasks\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n<p>Every developer working on web applications eventually faces a common challenge: how to run background tasks. Whether it&#8217;s sending emails, processing files, cleaning up data, or generating reports, these tasks shouldn&#8217;t slow down your app or your users.<\/p>\n\n\n\n<p>That\u2019s where Hangfire steps in. Instead of creating complex custom threads or Windows services, Hangfire offers a simple, powerful, and flexible way to handle background tasks in<a href=\"https:\/\/www.dotnetdevelopers.us\/\" target=\"_blank\" data-type=\"link\" data-id=\"https:\/\/www.dotnetdevelopers.us\/\" rel=\"noreferrer noopener\"> .NET<\/a>. You write your background code like any other method, and Hangfire handles the rest.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_Hangfire\"><\/span><strong>What is Hangfire?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Hangfire is an open-source library that enables you to perform background processing in .NET and .NET Core applications. You can enqueue long-running or scheduled tasks without blocking the main thread or freezing your app.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Key_Features\"><\/span><strong>Key Features:<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No Windows Service or separate process required<br><\/li>\n\n\n\n<li>Persistent storage using databases (SQL Server, PostgreSQL, etc.)<br><\/li>\n\n\n\n<li>Built-in Dashboard to monitor tasks<br><\/li>\n\n\n\n<li>Retries, logging, and error handling built in<br><\/li>\n\n\n\n<li>Supports various job types (fire-and-forget, delayed, recurring)<br><\/li>\n<\/ul>\n\n\n\n<p>In short, it&#8217;s background jobs made easy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Why_Use_Hangfire\"><\/span><strong>Why Use Hangfire?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Before we dive into code, let\u2019s quickly see why Hangfire is a solid choice:<\/p>\n\n\n\n<p>&nbsp;&nbsp;<strong>Ease of Use<\/strong> \u2013 No complex thread handling or task schedulers<br>&nbsp; <strong>Reliable<\/strong> \u2013 Jobs persist in storage (even after app restarts!)<br>&nbsp; <strong>Scalable<\/strong> \u2013 Works with small apps or big distributed systems<br>&nbsp; <strong>Secure Dashboard<\/strong> \u2013 Monitor jobs, retry failed ones, and see what\u2019s happening behind the scenes<br>&nbsp; <strong>Flexible<\/strong> \u2013 From basic jobs to recurring CRON-based scheduling<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Setting_Up_Hangfire_in_a_NET_Application\"><\/span><strong>Setting Up Hangfire in a .NET Application<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Let\u2019s break it down step-by-step.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Step_1_Install_Hangfire_via_NuGet\"><\/span><strong>Step 1: Install Hangfire via NuGet<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>bash<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>Install-Package Hangfire<\/p>\n\n\n\n<p>Install-Package Hangfire.SqlServer<\/p>\n\n\n\n<p>Install-Package Hangfire.AspNetCore<\/p>\n\n\n\n<p>If you&#8217;re using the .NET CLI:<\/p>\n\n\n\n<p>bash<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>dotnet add package Hangfire<\/p>\n\n\n\n<p>dotnet add package Hangfire.SqlServer<\/p>\n\n\n\n<p>dotnet add package Hangfire.AspNetCore<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Step_2_Configure_Hangfire_in_Startupcs_for_NET_Core\"><\/span><strong>Step 2: Configure Hangfire in <\/strong><strong>Startup.cs<\/strong><strong> (for .NET Core)<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Add Hangfire services and set up the dashboard and server.<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>public void ConfigureServices(IServiceCollection services)<\/p>\n\n\n\n<p>{<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;services.AddHangfire(config =&gt;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config.UseSqlServerStorage(Configuration.GetConnectionString(&#8220;DefaultConnection&#8221;)));<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;services.AddHangfireServer();<\/p>\n\n\n\n<p>}<\/p>\n\n\n\n<p>In the Configure method:<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>public void Configure(IApplicationBuilder app, IWebHostEnvironment env)<\/p>\n\n\n\n<p>{<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;app.. UseHangfireDashboard(); \/\/ Optional: enable dashboard at \/hangfire<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;\/\/ other middleware<\/p>\n\n\n\n<p>}<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Types_of_Background_Jobs_in_Hangfire\"><\/span><strong>Types of Background Jobs in Hangfire<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Hangfire supports several types of background jobs. Here\u2019s a quick overview:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"1_Fire-and-Forget_Jobs\"><\/span><strong>1. Fire-and-Forget Jobs<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>These are executed only once, immediately after being created.<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>BackgroundJob.Enqueue(() =&gt; Console.WriteLine(&#8220;Fire-and-forget job executed!&#8221;));<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"2_Delayed_Jobs\"><\/span><strong>2. Delayed Jobs<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Execute a job after a specified time delay.<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>BackgroundJob.Schedule(() =&gt; Console.WriteLine(&#8220;Delayed job!&#8221;), TimeSpan.FromMinutes(10));<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"3_Recurring_Jobs\"><\/span><strong>3. Recurring Jobs<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Run jobs on a recurring schedule using CRON expressions.<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>RecurringJob.AddOrUpdate(<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&#8220;my-recurring-job&#8221;,<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;() =&gt; Console.WriteLine(&#8220;Recurring job!&#8221;),<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;Cron.Daily);<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"4_Continuation_Jobs\"><\/span><strong>4. Continuation Jobs<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Run a job after another has completed.<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>var jobId = BackgroundJob.Enqueue(() =&gt; Console.WriteLine(&#8220;Initial job&#8221;));<\/p>\n\n\n\n<p>BackgroundJob.ContinueWith(jobId, () =&gt; Console.WriteLine(&#8220;Continuation job&#8221;));<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Using_the_Hangfire_Dashboard\"><\/span><strong>Using the Hangfire Dashboard<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>One of Hangfire\u2019s best features is its built-in dashboard. Just visit:<\/p>\n\n\n\n<p>bash<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>http:\/\/localhost:5000\/hangfire<\/p>\n\n\n\n<p>From there, you can:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>See scheduled, running, and completed jobs<br><\/li>\n\n\n\n<li>Retry failed jobs<br><\/li>\n\n\n\n<li>Monitor queues<br><\/li>\n\n\n\n<li>View job history and logs<br><\/li>\n<\/ul>\n\n\n\n<p>You can also protect the dashboard with authentication middleware to ensure only admins can access it.<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>app.UseHangfireDashboard(&#8220;\/hangfire&#8221;, new DashboardOptions<\/p>\n\n\n\n<p>{<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;Authorization = new[] { new MyAuthorizationFilter() }<\/p>\n\n\n\n<p>});<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Real-Life_Example_Sending_Emails_in_the_Background\"><\/span><strong>Real-Life Example: Sending Emails in the Background<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Let\u2019s say you want to send a welcome email after a user signs up. Instead of sending it directly, you can offload it to a Hangfire background job.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Step_1_Create_the_Job_Method\"><\/span><strong>Step 1: Create the Job Method<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>public class EmailService<\/p>\n\n\n\n<p>{<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;public void SendWelcomeEmail(string email)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;{<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ Your email-sending logic here<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine($&#8221;Welcome email sent to {email}&#8221;);<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n\n\n\n<p>}<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Step_2_Enqueue_the_Job\"><\/span><strong>Step 2: Enqueue the Job<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>var emailService = new EmailService();<\/p>\n\n\n\n<p>BackgroundJob.Enqueue(() =&gt; emailService.SendWelcomeEmail(&#8220;user@example.com&#8221;));<\/p>\n\n\n\n<p>Simple, clean, and efficient.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Best_Practices_for_Using_Hangfire\"><\/span><strong>Best Practices for Using Hangfire<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Here are some tips to make the most of Hangfire:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u00a0Keep your background jobs short and focused<br><\/li>\n\n\n\n<li>\u00a0Avoid using HttpContext or anything that depends on a request<br><\/li>\n\n\n\n<li>\u00a0Use dependency injection (DI) properly in job methods<br><\/li>\n\n\n\n<li>\u00a0Store logs and errors for debugging<br><\/li>\n\n\n\n<li>\u00a0Secure the Hangfire Dashboard in production<br><\/li>\n\n\n\n<li>\u00a0Use queues to prioritise or segregate tasks<br><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Error_Handling_and_Retries\"><\/span><strong>Error Handling and Retries<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Hangfire automatically retries failed jobs a few times. You can customise this:<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>[AutomaticRetry(Attempts = 3)]<\/p>\n\n\n\n<p>public void SomeMethod()<\/p>\n\n\n\n<p>{<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;\/\/ your logic<\/p>\n\n\n\n<p>}<\/p>\n\n\n\n<p>Or disable retries:<\/p>\n\n\n\n<p>csharp<\/p>\n\n\n\n<p>CopyEdit<\/p>\n\n\n\n<p>[AutomaticRetry(Attempts = 0)]<\/p>\n\n\n\n<p>Errors are logged and shown in the dashboard for easy tracking.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Advanced_Features_You_Should_Know\"><\/span><strong>Advanced Features You Should Know<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Here are a few more cool things Hangfire can do:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u00a0<strong>Batch Jobs:<\/strong> Group multiple jobs together<br><\/li>\n\n\n\n<li>\u00a0<strong>Job Filtering:<\/strong> Intercept jobs before\/after execution (logging, metrics, etc.)<br><\/li>\n\n\n\n<li>\u00a0<strong>Monitoring API:<\/strong> Use Hangfire\u2019s API to build custom dashboards<br><\/li>\n\n\n\n<li>\u00a0<strong>Job Queues:<\/strong> Assign jobs to specific queues for load balancing<br><\/li>\n\n\n\n<li>\u00a0<strong>Integration with Serilog, NLog, and more<\/strong><strong><br><\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"has-text-align-center has-large-font-size\"><strong>FAQs<\/strong><\/p>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1753782122555\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><span class=\"ez-toc-section\" id=\"Q1_Is_Hangfire_free_to_use\"><\/span>Q1: <strong> Is Hangfire free to use?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes, Hangfire is free and open-source under the MIT license. There\u2019s also a pro version with advanced features and support.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1753782147041\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><span class=\"ez-toc-section\" id=\"Q2_Can_I_use_Hangfire_with_NET_6\"><\/span>Q2: <strong>Can I use Hangfire with .NET 6+?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Absolutely! Hangfire supports .NET Framework, .NET Core, and .NET 5\/6\/7+.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1753782181460\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><span class=\"ez-toc-section\" id=\"Q3_Where_are_the_jobs_stored\"><\/span>Q3: <strong>Where are the jobs stored?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Jobs are stored in a persistent storage system. SQL Server is commonly used, but Hangfire also supports Redis, PostgreSQL, and others.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1753782202590\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><span class=\"ez-toc-section\" id=\"Q4_What_happens_if_the_server_crashes\"><\/span>Q4: <strong>What happens if the server crashes?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Since jobs are stored in a database, Hangfire will pick up right where it left off when the app restarts. Nothing is lost.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span><strong>Conclusion<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Scheduling background tasks doesn&#8217;t need to be a nightmare. With Hangfire, you can effortlessly run, monitor, and manage background jobs right from your .NET application, without breaking a sweat.<\/p>\n\n\n\n<p>From fire-and-forget to recurring CRON jobs, Hangfire\u2019s flexible design makes it the go-to solution for background processing in NET. Plus, with a dashboard that gives you full visibility, you&#8217;re always in control.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every developer working on web applications eventually faces a common challenge: how to run background tasks. Whether it&#8217;s sending emails, processing files, cleaning up data, or generating reports, these tasks shouldn&#8217;t slow down your app or your users. That\u2019s where Hangfire steps in. Instead of creating complex custom threads or Windows services, Hangfire offers a simple, powerful, and flexible way to handle background tasks in .NET. You write your background code like any other method, and Hangfire handles the rest. What is Hangfire? Hangfire is an open-source library that enables you to perform background processing in .NET and .NET Core applications. You can enqueue long-running or scheduled tasks without blocking the main thread or freezing your app. Key Features: In short, it&#8217;s background jobs made easy. Why Use Hangfire? Before we dive into code, let\u2019s quickly see why Hangfire is a solid choice: &nbsp;&nbsp;Ease of Use \u2013 No complex thread handling or task schedulers&nbsp; Reliable \u2013 Jobs persist in storage (even after app restarts!)&nbsp; Scalable \u2013 Works with small apps or big distributed systems&nbsp; Secure Dashboard \u2013 Monitor jobs, retry failed ones, and see what\u2019s happening behind the scenes&nbsp; Flexible \u2013 From basic jobs to recurring CRON-based scheduling Setting Up Hangfire in a .NET Application Let\u2019s break it down step-by-step. Step 1: Install Hangfire via NuGet bash CopyEdit Install-Package Hangfire Install-Package Hangfire.SqlServer Install-Package Hangfire.AspNetCore If you&#8217;re using the .NET CLI: bash CopyEdit dotnet add package Hangfire dotnet add package Hangfire.SqlServer dotnet add package Hangfire.AspNetCore Step 2: Configure Hangfire in Startup.cs (for .NET Core) Add Hangfire services and set up the dashboard and server. csharp CopyEdit public void ConfigureServices(IServiceCollection services) { &nbsp;&nbsp;&nbsp;&nbsp;services.AddHangfire(config =&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config.UseSqlServerStorage(Configuration.GetConnectionString(&#8220;DefaultConnection&#8221;))); &nbsp;&nbsp;&nbsp;&nbsp;services.AddHangfireServer(); } In the Configure method: csharp CopyEdit public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { &nbsp;&nbsp;&nbsp;&nbsp;app.. UseHangfireDashboard(); \/\/ Optional: enable dashboard at \/hangfire &nbsp;&nbsp;&nbsp;&nbsp;\/\/ other middleware } Types of Background Jobs in Hangfire Hangfire supports several types of background jobs. Here\u2019s a quick overview: 1. Fire-and-Forget Jobs These are executed only once, immediately after being created. csharp CopyEdit BackgroundJob.Enqueue(() =&gt; Console.WriteLine(&#8220;Fire-and-forget job executed!&#8221;)); 2. Delayed Jobs Execute a job after a specified time delay. csharp CopyEdit BackgroundJob.Schedule(() =&gt; Console.WriteLine(&#8220;Delayed job!&#8221;), TimeSpan.FromMinutes(10)); 3. Recurring Jobs Run jobs on a recurring schedule using CRON expressions. csharp CopyEdit RecurringJob.AddOrUpdate( &nbsp;&nbsp;&nbsp;&nbsp;&#8220;my-recurring-job&#8221;, &nbsp;&nbsp;&nbsp;&nbsp;() =&gt; Console.WriteLine(&#8220;Recurring job!&#8221;), &nbsp;&nbsp;&nbsp;&nbsp;Cron.Daily); 4. Continuation Jobs Run a job after another has completed. csharp CopyEdit var jobId = BackgroundJob.Enqueue(() =&gt; Console.WriteLine(&#8220;Initial job&#8221;)); BackgroundJob.ContinueWith(jobId, () =&gt; Console.WriteLine(&#8220;Continuation job&#8221;)); Using the Hangfire Dashboard One of Hangfire\u2019s best features is its built-in dashboard. Just visit: bash CopyEdit http:\/\/localhost:5000\/hangfire From there, you can: You can also protect the dashboard with authentication middleware to ensure only admins can access it. csharp CopyEdit app.UseHangfireDashboard(&#8220;\/hangfire&#8221;, new DashboardOptions { &nbsp;&nbsp;&nbsp;&nbsp;Authorization = new[] { new MyAuthorizationFilter() } }); Real-Life Example: Sending Emails in the Background Let\u2019s say you want to send a welcome email after a user signs up. Instead of sending it directly, you can offload it to a Hangfire background job. Step 1: Create the Job Method csharp CopyEdit public class EmailService { &nbsp;&nbsp;&nbsp;&nbsp;public void SendWelcomeEmail(string email) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ Your email-sending logic here &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine($&#8221;Welcome email sent to {email}&#8221;); &nbsp;&nbsp;&nbsp;&nbsp;} } Step 2: Enqueue the Job csharp CopyEdit var emailService = new EmailService(); BackgroundJob.Enqueue(() =&gt; emailService.SendWelcomeEmail(&#8220;user@example.com&#8221;)); Simple, clean, and efficient. Best Practices for Using Hangfire Here are some tips to make the most of Hangfire: Error Handling and Retries Hangfire automatically retries failed jobs a few times. You can customise this: csharp CopyEdit [AutomaticRetry(Attempts = 3)] public void SomeMethod() { &nbsp;&nbsp;&nbsp;&nbsp;\/\/ your logic } Or disable retries: csharp CopyEdit [AutomaticRetry(Attempts = 0)] Errors are logged and shown in the dashboard for easy tracking. Advanced Features You Should Know Here are a few more cool things Hangfire can do: FAQs Conclusion Scheduling background tasks doesn&#8217;t need to be a nightmare. With Hangfire, you can effortlessly run, monitor, and manage background jobs right from your .NET application, without breaking a sweat. From fire-and-forget to recurring CRON jobs, Hangfire\u2019s flexible design makes it the go-to solution for background processing in NET. Plus, with a dashboard that gives you full visibility, you&#8217;re always in control.<\/p>\n","protected":false},"author":1,"featured_media":256,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-239","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"_links":{"self":[{"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/posts\/239","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/comments?post=239"}],"version-history":[{"count":3,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/posts\/239\/revisions"}],"predecessor-version":[{"id":258,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/posts\/239\/revisions\/258"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/media\/256"}],"wp:attachment":[{"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/media?parent=239"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/categories?post=239"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dotnetdevelopers.us\/blogs\/wp-json\/wp\/v2\/tags?post=239"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}