Background tasks run behind the scenes without any user intervention. It could be triggered based on time or some other external events. We can use background tasks in many places. For examples:
- Clean up database or file system every day
- Perform some high CPU intensive work asynchronously
- Process messages from a queue every X minutes
- Refresh cache every X minutes
- Send payslip to employees every month
- Send performance reports to stakeholders every day
Hosted Service
A hosted service is a class that contains background task logic that implements directly from an IHostedService
interface or a BackgroundService
abstract class.
However, we can also create background tasks without using a hosted service. So the next question is why I should use hosted service to create background tasks. The answer is simple:
- The hosted service execution is coordinated with the lifetime of the application
- And, it allows doing graceful clean-up when the application is shutting down.
In general, we can colocate the hosted services along with web applications. However, if we want to execute the background tasks out of the web application, we can use the WorkerService
template.
Configuration
The hosted service is registered within the familiar ConfigureServices
method. In the below code, the DbMigrationHostedService
will start first, then it will kick start the RefreshCacheHostedService
, and then it will start the Kestral web server.
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<DbMigrationHostedService>();
services.AddHostedService<RefreshCacheHostedService>();
}
}
However, if we want to run the Kestral web server before starting the hosted services, then we can register the hosted service in Program.cs
:
public class Program
{
...
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.AddHostedService<DbMigrationHostedService>();
services.AddHostedService<RefreshCacheHostedService>();
});
}
}
Cancellation Token
The default cancellation token timeout is 5 seconds in the .NET Core application, so any remaining operations after the default timeout will be aborted. To achieve the graceful shutdown, we need to execute the stopAsync
within 5 seconds. However, sometimes it is truly impossible to do the cleanup operation within 5 seconds. In such cases, you can change the default shutdown timeout limit:
public class Program
{
...
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = TimeSpan.FromSeconds(15);
});
...
});
}
Here is the youtube link of my presentation at Azure community meetup, Singapore, where I explained different options available for creating background tasks in detail:
And, here is the source code link for the same: GitHub