Running Background Tasks In ASP.NET Core
Tags: aspnet, aspnetcore, dotnet, csharp
Published: 2023-09-16 10:50:53

---
title: Running Background Tasks In ASP.NET Core
published: true
date: 2022-12-03 00:00:00 UTC
tags: aspnet,aspnetcore,dotnet,csharp
canonical_url: https://www.milanjovanovic.tech/blog/running-background-tasks-in-asp-net-core
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sl20yrzx5r0f7ngn7ql2.png
---
In this week's newsletter we will talk about running **background tasks** in **ASP.NET Core**. After reading this newsletter, you will be able to set up a **background task** and have it up and running within minutes.

**Background tasks** are used to offload some work in your application to the background, outside of the normal application flow. A typical example can be asynchronously processing messages from a queue.

I will show you how to create a simple **background task** that runs once and completes.

And you will also see how to configure a continuous **background task** , that repeats after a specific period.

Let's dive in.

## Background Tasks With IHostedService

You can define a **background task** by implementing the `IHostedService` interface. It has only two methods.

Here's what the `IHostedService` interface looks like:

```csharp
public interface IHostedService
{
    Task StartAsync(CancellationToken cancellationToken);

    Task StopAsync(CancellationToken cancellationToken);
}
```

All you have to do is implement the `StartAsync` and `StopAsync` methods.

Inside of `StartAsync` you would usually perform the background processing. And inside of `StopAsync` you would perform any cleanup that is necessary, such as disposing of resources.

To configure the **background task** you have to call the `AddHostedService` method:

```csharp
builder.Services.AddHostedService<MyBackgroundTask>();
```

Calling `AddHostedService` will configure the **background task** as a **singleton** service.

So does dependency injection still work in `IHostedService` implementations?  
Yes, but you can only inject **transient** or **singleton** services.

However, I don't like to implement the `IHostedService` interface myself. I prefer using the `BackgroundService` class instead.

## Background Tasks With BackgroundService

The `BackgroundService` class already implements the `IHostedService` interface, and it has an `abstract` method that you need to override - `ExecuteAsync`. When you are using the `BackgroundService` class, you only have to think about the operation you want to implement.

Here's an example **background task** that runs **EF** migrations:

```csharp
public class RunEfMigrationsBackgroundTask : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public RunEfMigrationsBackgroundTask(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using IServiceScope scope = _serviceProvider.CreateScope();

        await using AppDbContext dbContext =
            scope.ServiceProvider.GetRequiredService<AppDbContext>();

        await dbContext.Database.MigrateAsync(stoppingToken);
    }
}
```

The **EF** `DbContext` is a **scoped** service, which we can't inject directly inside of `RunEfMigrationsBackgroundTask`. We have to inject an instance of`IServiceProvider` which we can use to create a custom service scope, so that we can resolve the scoped `AppDbContext`.

I would _not recommend_ running the `RunEfMigrationsBackgroundTask` in production. **EF** migrations can easily fail and you'll run into problems. However, I think it's perfectly fine for local development.

## Periodic Background Tasks

Sometimes we want run a **background task** continuously, and have it perform some operation on repeat. For example, we want consume messages from a queue every ten seconds. How do we build this?

Here's an example `PeriodicBackgroundTask` to get you started:

```csharp
public class PeriodicBackgroundTask : BackgroundService
{
    private readonly TimeSpan _period = TimeSpan.FromSeconds(5);
    private readonly ILogger<PeriodicBackgroundTask> _logger;

    public PeriodicBackgroundTask(ILogger<PeriodicBackgroundTask> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using PeriodicTimer timer = new PeriodicTimer(_period);

        while (!stoppingToken.IsCancellationRequested &&
               await timer.WaitForNextTickAsync(stoppingToken))
        {
            _logger.LogInformation("Executing PeriodicBackgroundTask");
        }
    }
}
```

We're using a [PeriodicTimer](https://learn.microsoft.com/en-us/dotnet/api/system.threading.periodictimer?view=net-6.0)to asynchronously wait for a given period, before executing our **background task**.

## What If You Need A More Robust Solution?

It should be obvious by now that `IHostedService` is useful when you need simple **background tasks** that are running while your application is running.

What if you want to have a scheduled **background task** that runs at 2AM every day?

You can probably build something like this yourself, but there are existing solutions that you should consider first.

Here are two popular solutions for running **background tasks** that I worked with before:

- [Quartz](https://www.quartz-scheduler.net/)
- [Hangfire](https://www.hangfire.io/)

I also have an example of [using Quartz for processing Outbox messages](https://youtu.be/XALvnX7MPeo) on my YouTube channel that you can take a look at.

* * *

**P.S. Whenever you're ready, there are 2 ways I can help you:**

1. [**Pragmatic Clean Architecture:**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting) This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. [**Join 950+ students here.**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting)

2. [**Patreon Community:**](https://www.patreon.com/milanjovanovic) Think like a senior software engineer with **access to the source code** I use in my YouTube videos and **exclusive discounts** for my courses. [**Join 820+ engineers here.**](https://www.patreon.com/milanjovanovic)