# Running Background Tasks In ASP.NET Core

> In this week's newsletter we will talk about running background tasks in ASP.NET Core. Background tasks offload work to the background, outside of the normal application flow. I will show you a background task that runs once and completes, and one that repeats after a specific period.

Published: 2022-12-03. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/running-background-tasks-in-asp-net-core

To run a **background task** in ASP.NET Core, implement the `IHostedService` interface, or inherit from the `BackgroundService` class and override `ExecuteAsync`.
Register the task with `builder.Services.AddHostedService`, and it runs as a singleton service alongside your application.
For repeating work, use a `PeriodicTimer` inside `ExecuteAsync` to run the task on a fixed period.

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**](https://milanjovanovic.tech/blog/ef-core-migrations-best-practices):

```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.

---

## Frequently asked questions

### How do you run a background task in ASP.NET Core?

Implement the IHostedService interface, or more conveniently inherit from the BackgroundService class and override ExecuteAsync. Register the task with builder.Services.AddHostedService, which configures it as a singleton service that runs alongside your application.

### What is the difference between IHostedService and BackgroundService?

IHostedService is the raw interface with StartAsync and StopAsync methods that you implement yourself. BackgroundService already implements IHostedService and exposes a single abstract ExecuteAsync method to override, so you only have to think about the operation you want to implement.

### Can you inject scoped services into a BackgroundService?

Not directly. A hosted service is a singleton, so you can only inject transient or singleton services. For a scoped service like an EF Core DbContext, inject IServiceProvider, create a service scope, and resolve the scoped service from that scope.

### How do you run a periodic background task in ASP.NET Core?

Use a PeriodicTimer inside a BackgroundService. In ExecuteAsync, loop while the stopping token is not cancelled and await WaitForNextTickAsync, doing your work on each tick. The timer asynchronously waits for the configured period between executions.

### When should you use Quartz or Hangfire instead of a hosted service?

IHostedService fits simple background tasks that run while your application is running. For scheduled jobs, such as a task that runs at 2AM every day, consider an existing solution like Quartz or Hangfire before building your own scheduler.

### Should you run EF Core migrations from a background service?

I would not recommend it in production, because EF migrations can easily fail and you'll run into problems. It is perfectly fine for local development, where a BackgroundService can apply migrations at startup using a scoped DbContext.
