Background service management using Hosted Service

Written By Sahil Ganguly

Last Updated: February 6, 2024
July 25, 2023

Want to receive our Blog every month?

Introduction

Long running tasks are very common in an API application. Tasks like data synchronization, periodic updates and background processing can be done asynchronously.

ASP.NET Core Hosted Service can be used to implement background tasks. Hosted Service was introduced in ASP.NET Core 3.1 and are an excellent way to run background tasks. 

They can be run on an ASP.NET Core web application. This is ideal if we need to update something that runs in the background that could affect all users. 

What is a Hosted Service?

Hosted Service is an interface provided by the Microsoft.Extensions.Hosting namespace in .NET Core. It allows developers to define background tasks or services that run as part of the application’s lifetime. It provides a structured and managed way to execute long-running processes, ensuring they start and stop gracefully during application startup and shutdown.  

We can implement Background Services using three Hosted Services in .NET:

  • Using IHostedService that activates a scoped service.
  • inheriting BackgroundService class that runs on a timer.
  • Using QueuedBackground tasks that run sequentially.  

Lets dive deep into the approach that uses IHostedService interface and implements background service for the long running tasks.

IHostedService implementation 

We first create a class that inherits the IHostedService Interface. The Interface contains two methods:  

  • StartAsync(CancellationToken): The StartAsync function defines the logic of the long running process that we must execute. It can be a loop or an asynchronous method that waits for an event to occur.  
  • StopAsync(CancellationToken): This method is used to gracefully stop the process when the application is shutting down.  

We need to register the HostedService in the dependency injection container.  

This can be done in the ConfigureServices method in the Startup Class by using the method services.AddHostedService where T is the type of the HostedService class.  

Starting the Hosted Service: When the application starts, the HostedService will be automatically commenced by the framework. The StartAsync method is called, and the process starts running.  

Shutting down the Hosted Service: When the application is shutting down the Hosted Service will be gracefully stopped. The StopAsync method is called that will stop the long running process, here we can also do the final cleanup. This method makes sure that the long running process stops correctly without terminating any process abruptly.

IHostedService usage

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;

public class LongRunningProcess : IHostedService, IDisposable
{
    private Timer _timer;
    public Task StartAsync(CancellationToken cancellationToken)
    {
        // Create a timer that 	executes the DoWork method every 5 seconds  
        Console.WriteLine("Long-running process started."); 
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        // Perform the long-running task here  
        Console.WriteLine("Performing a task...");
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        // Stop the timer
        Console.WriteLine("Long-running process stopping.");
        _timer?.Change(Timeout.Infinite, 0);  
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}

Register the Hosted Service while bootstrapping

public class Program
{
    public static async Task Main(string[] args)
    {
        var hostBuilder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                // Register the LongRunningProcess as a hosted service
                services.AddHostedService<LongRunningProcess>();
            });
        await hostBuilder.RunConsoleAsync();
     }
}

When we run this code, we will see the message “Long-running process started” followed by the “Performing a task…” message every 5 seconds.  

When we stop the application, it will print “Long running process stopping” indicating a graceful shutdown of the long-running process. 

Advantages of using background services with Hosted Service

  • Improved Scalability and Performance: Implementation of long running processes in the background will not hamper the flow of the running application threads. This will increase the performance of the application  
  • Easy Debugging: Implementing long running processes using Hosted Services provides a better way to handle and debug the code as it can be managed independently.
  • Using Dependency Injection: Integrating more services with HostedServices using Dependency Injection would mean running many background processes simultaneously without tightly coupling any of them. 

Conclusion

Long-running processes are a common requirement in many applications and managing them effectively is crucial for the stability and performance of the software. The Hosted Service feature in .NET Core provides a robust and structured approach to tackle this challenge. By implementing the IHostedService interface, we can ensure the long-running processes to start and stop gracefully, improving the overall performance of the application. 

Keep up to date with Osmosys Blog!