Implement A Background Task Using IHostedService In ASP.NET Core


In our previous article, we saw the Implementation of a Background Task using BackgroundService with example. If you are new in background task implementation using Background Service class, then please read the below article so you will get a better understanding.
In the above URL, you will get an idea for IHostedService and how it exactly works. 
If you want to implement background task using BackgroundService with example see below URL, which I explained in the previous article
In this article, we will see the IHostedService article with an example. For the implementation of a background task, we dont need any Nuget packages or anything, etc. It is in core ASP.NET infrastructure itself. We know a background task can be implemented in two main ways in ASP.NET Core, using BackgroundService Class and IHostedService. IHostedService as Interface.
It defines two methods which are StartAsync(CancellationToken) and StopAsync(CancellationToken). StartAsync is nothing but a trigger when the application host to ready to start the service. It contains the logic to start background tasks. StartAsync is called before the app request processing the pipeline is configured (Startup. Configure) and the server is started and the IApplicationLifetime.ApplicationStarted is triggered.StopAsync is triggered when the application host is performing a graceful shutdown.It contains the logic to end the background task. The IHostedService interface provides a nice way to properly start Background tasks in web applications.
Let's try to understand it by using the below example,
Previously, we saw a particular URL and when it will be Up and when it will be Down. This was maintained in a txt file using BackgroundService Class.We are trying to acheive the same here by using the IHostedService Interface.
Step 1
As you can see in the below diagram, the Worker class is implemented below:
  1. public class Worker: IWorker  
  2.     {  
  3.         private readonly ILogger _logger;  
  4.         private HttpClient httpClient;  
  5.         public Worker(ILogger<Worker> logger)  
  6.         {  
  7.             this._logger = logger;  
  8.         }  
Above, we just used a logger in the constructor for logging the output.
  1. public async Task DoWork(CancellationToken cancellationToken)  
  2. {  
  3.     httpClient = new HttpClient();  
  4.     while (!cancellationToken.IsCancellationRequested)  
  5.     {  
  6.         try  
  7.         {  
  8.             var result = await httpClient.GetAsync("");  
  9.             if (result.IsSuccessStatusCode)  
  10.             {  
  11.                 _logger.LogInformation("The Website is Up.Status Code {StatusCode}", result.StatusCode);  
  12.             }  
  13.             else  
  14.             {  
  15.                 _logger.LogError("The Website is Down.Status Code {StatusCode}", result.StatusCode);  
  16.             }  
  17.         }  
  18.         catch (Exception ex)  
  19.         {  
  20.             _logger.LogError("The Website is Down {0}.", ex.Message);  
  21.         }  
  22.         finally  
  23.         {  
  24.             await Task.Delay(1000 * 5, cancellationToken);  
  25.         }  
  26.     }  
  27. }  
In the above code, we specify the URL whose status we need to check every 5 seconds.
Step 2
In the below diagram as you can see BackgroundWriter class inherited IHostedService Interface.Also, those two methods which we need to implement StartAsync and StopAsync is also present.In StartAsync, we are calling our main logic method which is DoWork and in the StopAsync method, HttpClient does indirectly implement an IDisposable interface the standard usage of HttpClient is not to dispose of it after every request.Releases unmanaged resources used by the HttpClient and optionally disposes of the managed resources.
  1. public class BackgroundWriter : IHostedService  
  2. {  
  3.     private readonly ILogger<BackgroundWriter> _logger;  
  4.     private readonly IWorker _worker;  
  5.     private HttpClient httpClient;  
  6.     public BackgroundWriter(ILogger<BackgroundWriter> logger, IWorker worker)  
  7.     {  
  8.         _logger = logger;  
  9.         this._worker = worker;  
  10.     }  
  11.     public async Task StartAsync(CancellationToken cancellationToken)  
  12.     {  
  13.         await _worker.DoWork(cancellationToken);              
  14.     }  
  16.     public Task StopAsync(CancellationToken cancellationToken)  
  17.     {  
  18.         httpClient.Dispose();  
  19.         return Task.CompletedTask;  
  20.     }  
  21. }  
Step 3
As you can see below diagram, you need to install Serilog from Nuget for writing texts into a textfile.
There are two packages which you need to install here:
  • Serilog.AspNetCore
  • Serilog.Sinks.File 
Step 4
In the below diagram, you will see I defined the path there where our file was stored. In this file, we will get the status of our URL if it is running or down every 5 seconds.
  1. public static void Main(string[] args)  
  2. {  
  3.     Log.Logger = new LoggerConfiguration()  
  4.                     .MinimumLevel.Debug()  
  5.                     .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)  
  6.                     .Enrich.FromLogContext()  
  7.                     .WriteTo.File(@"C:\Service\LogFile.txt")  
  8.                     .CreateLogger();  
  9.     try  
  10.     {  
  11.         Log.Information("Starting up the Service");  
  12.         CreateHostBuilder(args).Build().Run();  
  13.         return;  
  14.     }  
  15.     catch (Exception ex)  
  16.     {  
  17.         Log.Fatal(ex, "There was a problem starting Service");  
  18.         return;  
  19.     }  
  20.     finally  
  21.     {  
  22.         Log.CloseAndFlush();  
  23.     }  
  24.     //CreateHostBuilder(args).Build().Run();  
  25. }  
Step 5
In this below diagram, we need to configure our Interface and Class into Dependency Injection.
  1. public Startup(IConfiguration configuration)  
  2. {  
  3.     Configuration = configuration;  
  4. }  
  6. public IConfiguration Configuration { get; }  
  8. // This method gets called by the runtime. Use this method to add services to the container.  
  9. public void ConfigureServices(IServiceCollection services)  
  10. {  
  11.     services.AddControllers();  
  12.     services.AddSingleton<IWorker, Worker>();  
  13. }  
Step 6
This is the last step where you will configure your service with Dependency Injection.
  1. public static IHostBuilder CreateHostBuilder(string[] args) =>  
  2.             Host.CreateDefaultBuilder(args)  
  3.                 .ConfigureWebHostDefaults(webBuilder =>  
  4.                 {  
  5.                     webBuilder.UseStartup<Startup>();  
  6.                 }).ConfigureServices(service =>  
  7.                    service.AddHostedService<BackgroundWriter>())  
  8.                          .UseSerilog();  
Now you guys should have a better understanding on Background Task implementation. In this article, we saw an example for IHostedService. Let me know if you have any queries.