.NET Background Tasks: Understanding the Differences Between BackgroundService and IHostedService

Background tasks are the elements of an application that work behind the scenes without input or interaction from the end user. They usually involve processes that run for long periods or require continuous updates to the host application’s parameters.

As background tasks can run concurrently with foreground operations, developers typically assign them to run do so to improve performance. One common example is to periodically clean up unused data after a specified duration, similar to clearing a web browser’s cache to improve loading speed.

One of the easiest ways to start implementing background tasks into your ASP.NET application is through the IHostedService interface. This interface allows you to run background tasks at specific intervals continuously, which you can designate with every application instance or set up as a standalone project. However, IHostedService is typically relegated to short-running tasks.

In contrast, BackgroundService was introduced as an extension for long-running or concurrent tasks.

This article will review key differences between these two services and their methods, including their benefits, use cases, and suggested best practices.

Working with BackgroundService and IHostedService

To better understand the relationship between BackgroundService and IHostedService, let’s first cover how each interface works.

IHostedService handles your background tasks using special classes called hosted services. In ASP.NET, these are objects of the reference type that implement the IHostedService interface. Hosted services contain many built-in features, such as logging, dependency injection, and configuration. They work in the background to perform operations, listen to queue messages like history logs or order transactions, or invalidate the cache by removing stale data and refreshing the content.

IHostedService offers two methods for orchestrating background tasks:

  • StartAsync starts a background task. No other services can start until the StartAsync method concludes, which is why using IHostedService is not advisable for long-running or concurrent tasks.
  • StopAsync ends the background task and is triggered when the application host performs a graceful shutdown. However, if an error or unexpected failure occurs in an application, StopAsync may not be called.

Because the StartAsync method makes it difficult — if not impossible — to perform long-running tasks using the default IHostedService interface, BackgroundService was added in ASP.NET Core 3.0 as a base or helper class.

In many respects, BackgroundService can be viewed as a simplified means of accomplishing the same goals using less code. Unlike IHostedService’s two-method approach, BackgroundService uses the template method pattern to encapsulate every step into its singular ExecuteAsync method. This saves you the work of defining StartAsync, StopAsync, and other parameters.

So, instead of directly implementing IHostedService, you can use the simplified ExecuteAsync method from BackgroundService. However, you can override the StartAsync and StopAsync methods if you intend to do so in a BackgroundService. This could come in handy when your application demands that you execute the methods in a custom manner.

One of the critical differences between IHostedService and BackgroundService is that the latter allows you to await a task. Awaiting a task checks if the task is complete. If not, the method pauses and returns to the caller until further notice. The StartAsync method does not have that luxury because the hosted service automatically starts when the application builder becomes active.

Another difference is that in the ExecuteAsync method, you have to handle the CancellationToken to stop your method, although it has a default timeout of five seconds. You can modify the timeout period with the ShutdownTimeout property when using Generic Host or Web Host. Furthermore, you can also use the BackgroundService when you do not want to handle the CancellationToken explicitly or want to optimize your code to be shorter.

In web applications, the CancellationToken is used to stop long-running tasks when the user stops making a request or refreshes a web page.

Implementing IHostedService and BackgroundService

To illustrate the difference between IHostedService and BackgroundService implementations, let’s look at an example. In this section, we will create a simple script for running a background task using IHostedService, then rewrite it using the BackgroundService method. This hosted service will repeatedly print “Working behind the scenes” every five seconds.

In your .NETCore project, create a new class called SampleBackgroundTaskService and implement the following code:

public class SampleBackgroundTaskService : IHostedService 
{
private Timer _timer = null;
public Task StartAsync(CancellationToken cancellingToken)
{
_timer = new Timer(ActionToBePerformed, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));

return Task.CompletedTask; }
void ActionToBePerformed(object state)
{
Debug.WriteLine("Working behind the scenes...");
}

public Task StopAsync(CancellationToken cancellingToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
}

This code used the following steps:

  • Implement the IHostedService interface.
  • Initialize a variable called _timer to use in the StartAsync and StopAsync methods from the implemented IHostedInterface. The timer runs the ActionToBePerformed method every five seconds.
  • The ActionToBePerformed method block contains the code to print “Working behind the scenes.”

After creating your background service class, you have to add the SampleBackgroundTaskService to the ConfigureServices method in your project’s startup.cs file. This code will enable the application to recognize and call the background service task.

public void ConfigureServices(IServiceCollection services) 
{
services.AddHostedService<SampleBackgroundTaskService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

To rewrite the same function from the SampleBackgroundTaskService above using BackgroundService, set up the class as shown in the following code:

public class SampleBackgroundTaskService : BackgroundService 
{
protected async override Task ExecuteAsync(CancellationToken cancellingToken)
{
while(!cancellingToken.IsCancellationRequested)
{
Debug.WriteLine("Working behind the scenes...");
await Task.Delay(5000, cancellingToken);
}
}
}

The above code inherits BackgroundService instead of IHostedService. However, it only uses the ExecuteAsync method because the implementation handles the starting and stopping mechanisms, as well as the CancellationToken operation.

Note: You still have to maintain the class addition to the list in the ConfigureServices method of the startup.cs file.

IHostedService is generally suitable for extract, transform, and load (ETL) operations, clearing caches, moving files, and reading data from databases. However, because the StartAsync method does not allow subsequent tasks to begin until the initial task is completed, it is ill-equipped for long-running or concurrent tasks.

Meanwhile, BackgroundService’s capacity for long-running tasks makes it the best choice for operations like processing data queries, enabling execution logging, or sending emails outside of a web thread. However, IHostedService’s allowance for graceful clean-up processes enables it to cancel background tasks, as it shuts down alongside the web application.

Conclusion

Background tasks are necessary when running certain long-running operations or those that you cannot defer to another time. ASP.NET enables you to easily create background tasks in applications using tools such as IHostedService and BackgroundService.

IHostedService conveniently handles short-running tasks using the StartAsync and StopAsync methods. It functions well for tasks like listening to queue messages and invalidating or clearing caches.

BackgroundService, on the other hand, runs long-running IHostedService tasks with a single method — ExecuteAsync. It can be used for logging and monitoring, scheduling, and more. You can implement the one you choose within your .NET application based on the type of task you want to run in the background.

Was this article helpful?
Monitor your applications with ease

Identify and eliminate bottlenecks in your application for optimized performance.

Related Articles

Write For Us

Write for Site24x7 is a special writing program that supports writers who create content for Site24x7 "Learn" portal. Get paid for your writing.

Write For Us

Write for Site24x7 is a special writing program that supports writers who create content for Site24x7 “Learn” portal. Get paid for your writing.

Apply Now
Write For Us