Background Tasks in .NET

Background Tasks in .NETIt seems like every application I’ve ever written, at some point needs to run a task in the background that is to be scheduled at some point in the future.

My need for tasks as reoccurring batch jobs has decreased significantly over the years because of my applications being more event driven.

Nowadays, I will often use Event Stores Persistent Subscriptions with my event stream as a queue.  However, I’m not event sourcing all parts of the application and not always using Event Store.

Hangfire

I stumbled upon Hangfire a couple years ago when trying to find solution to running background tasks in a .NET console application running as a service with Topshelf.

When I was trying to find a solution, I need to have tasks distributed across multiple worker services.  Hangfire has this problem solved.

An easy way to perform fire-and-forget, delayed and recurring tasks inside ASP.NET applications. No Windows Service required.

Backed by persistent storages. Open and free for commercial use.

Background method calls and their arguments are serialized and may overcome the process boundaries.

You can use Hangfire on different machines to get more processing power with no configuration – synchronization is performed automatically.

Getting Started

The docs are really good over at the Hangfire site, so I don’t want to rewrite what is already over there.  I do however just want to give you enough to show you how simple it is to use and let you decide if its a viable solution for you.

There are two ways in which you can get started.  If you plan on using Hangfire within an ASP.NET Web Application and want to use SQL Server as your storage mechanism, then you can install the boostrapper package which has everything you need.

Install-Package HangFire -Version 1.5.6

If you plan on using in any other project type (Windows Service, Console, OWIN-Compatible Web Application, Azure Worker Role) or different storage mechanism, you can install the Hangfire.Core.

Install-Package HangFire.Core -Version 1.5.6

Configuration

Configuration is the same if you are in an ASP.NET Web Application or any other project type.  What differs is where you put this configuration.

But it is incredibly straight forward.  You simply use the GlobalConfiguration class to configure the entry point.

Server

The server is what processes the background tasks we will define later.  In order to create a server, you simply create a BackgroundJobServer.  This can be called from any project you wish to act as a Hangfire server.  As with configuration, where you place create the BackgroundJobServerwill depend on the project type.

Create Background Task

There are different types of background tasks that we can now create from any other project type.  These calls do not need to be made from the same application as the server.

  • Fire-and-forget
  • Delay
  • Recurring

Any type of Tasks can be called from any client and it will be executed on a Hangfire server.

Fire-and-forget

You simply call the Enqueue with your action you want to invoke on the server.

The Enqueue method does not call the target method immediately, it runs the following steps instead:

  1. Serialize a method information and all its arguments.
  2. Create a new background job based on the serialized information.
  3. Save background job to a persistent storage.
  4. Enqueue background job to its queue.

For my example, I’m going to Enqueue a new task in the same application as my server.

When you run this application, here is the console output.

Hangfire

Delay & Reoccurring

You can also create tasks that are delayed from the time of creation.  This may be useful for possibly invoking a method to send to a user a couple days after they have signed up for a trial of your software.

You can also create reoccurring tasks and supports CRON expressions.

Data Storage

There are fair amount of stable different storage providers such as Redis, SQL Server, SQL Azure, Mongo, PostgreSql.   Be sure to check out each of the data providers github/website to make sure they are still active and production ready as it seems a few may be out of date or experimental.

I highly recommend you check out this project if you are looking for this type of functionality.

Comments

I’d love to hear how you handle running background tasks. Are you using some other tool?  Please share in the comments below or on twitter.

Related Posts

  • Mediator Pattern with Hangfire
  • Yeah, Hangfire is fantastic! We use it with the Redis store and can’t say enough good things about it. It’s great to just be able to throw serializable MediatR Request objects up in a queue to be executed in the background. Commands all the way down FTW 🙂

    • Exactly! I use the same approach. I generally handle the initial command to satisfy the request then offload to Hangfire to do some additional work in the background.

      I think my next post is going to elaborate on this exactly. On how you can create a command (MediatR Request), send off to Hangfire and have it run in the background.

      Thanks for the feedback!

  • Pingback: The Morning Brew #2080 | Tech News()

  • Petr Vojtechovsky

    Hi Derek

    Hangfire is super tool, no doubts about that

    Just couple of technical things to your blog.

    1) Data Storage> (typo) SQLight => SQLite

    2) Hangfire does not supports all data stores list in the link.
    SQLite, for example, is definitely not working

    Cheers
    Petr

    • Petr,

      Thanks for the feedback. I’ve updated accordingly. I’ve been looking for a MySQL provider and there are a couple out on GitHub but not entirely sure how complete they are yet.

  • Pingback: Compelling Sunday – 27 Posts on Programming and QA()

  • Pingback: Szumma #037 – 2016 17. hét | d/fuel()

  • Pingback: Mediator Pattern with Hangfire - CodeOpinion()

  • Pingback: The week in .NET – 5/3/2016 | .NET Blog()

  • Pingback: The week in .NET – 5/3/2016 | Tech News()

  • Hi Derek,

    I used WebJobs on Azure in my last project. WebJobs worked really well for me – I especially liked its reliable queues. However I did find diagnosing problems a bit difficult. I think I could have used HangFire instead.

    A couple of questions from your experience. What is HangFire like for testing and debugging background tasks? Also, what happens if you publish/replace an ASP.NET application – I assume any enqueued messages still get honoured as they are stored in a persistent store – correct?

    • In terms of debugging locally, it’s as if you are debugging any other console or web app. Once an job is invoked you can break where the start of your code (the job target) would occur. The UI does provide pretty decent messages if something goes wrong to calling your target method. It does automatically do retries if the invocation failes (10 by default).

      For logging in general, I’ve been using a combination of log4net and Exceptionless.

  • Pingback: My readings in 2016 week 18 | My path to become awesome dev()

  • great article thanks!