I would like to present how to make background services in asp.net core with IHostedService.
What is IHostedService
You can use IHostedService to create background tasks in asp.net core projects. I used Quartz.NET to similar purposes in the past. I do not want to compare them because it is not purpose of this article :-). So, if you want to create background task you can do that by implementing IHostedService. It’s very simple 🙂
How can we use it
I would like to create very very simple background task which creates GUIDs every 10 seconds and save them in memory cache. Don’t worry I’ll display them on website 😉 We need to create some base class BackgroundService. I create something similar like BackgroundService from here
BackgroundService:
using Microsoft.Extensions.Hosting; using System; using System.Threading; using System.Threading.Tasks; namespace Letys.HostedService.Example.Services { public abstract class BackgroundService : IHostedService, IDisposable { private Task task; private readonly CancellationTokenSource cancellationTokens = new CancellationTokenSource(); protected abstract Task ExecuteAsync(CancellationToken stoppingToken); public virtual Task StartAsync(CancellationToken cancellationToken) { this.task = this.ExecuteAsync(this.cancellationTokens.Token); return this.task.IsCompleted ? this.task : Task.CompletedTask; } public virtual async Task StopAsync(CancellationToken cancellationToken) { if (this.task != null) { try { this.cancellationTokens.Cancel(); } finally { await Task.WhenAny(task, Task.Delay(Timeout.Infinite, cancellationToken)); } } } public virtual void Dispose() { this.cancellationTokens.Cancel(); } } }
After that we can create our background task class – ExampleGuidService:
using Letys.HostedService.Example.Models; using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Letys.HostedService.Example.Services { public class ExampleGuidService : BackgroundService { public const string ExampleGuidsKey = "ExampleGuids"; private IMemoryCache memoryCache; public ExampleGuidService(IMemoryCache memoryCache) { this.memoryCache = memoryCache; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { GenerateNewExampleGuid(); await Task.Delay(1000*10, stoppingToken); } } private void GenerateNewExampleGuid() { ExampleGuid example = new ExampleGuid { Timestamp = DateTime.Now, Guid = Guid.NewGuid() }; var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromHours(24)); if (!this.memoryCache.TryGetValue(ExampleGuidService.ExampleGuidsKey, out List<ExampleGuid> cacheEntry)) { cacheEntry = new List<ExampleGuid>(); } cacheEntry.Add(example); this.memoryCache.Set(ExampleGuidService.ExampleGuidsKey, cacheEntry, cacheEntryOptions); } } }
This is our ExampleGuid:
using System; namespace Letys.HostedService.Example.Models { public class ExampleGuid { public Guid Guid { get; set; } public DateTime Timestamp { get; set; } } }
We can register ExampleGuidService in Startup.cs:
public void ConfigureServices(IServiceCollection services) { services.AddMemoryCache(); services.AddMvc(); services.AddSingleton<IHostedService, ExampleGuidService>(); }
Now we can add ExampleGuids action and view:
public IActionResult ExampleGuids() { if (!this.memoryCache.TryGetValue(ExampleGuidService.ExampleGuidsKey, out List cacheEntry)) { cacheEntry = new List(); } return View(cacheEntry); }
@model IEnumerable<Letys.HostedService.Example.Models.ExampleGuid> @{ ViewData["Title"] = "ExampleGuids"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>ExampleGuids</h2> <p> <a asp-action="Create">Create New</a> </p> <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.Guid)</th> <th>@Html.DisplayNameFor(model => model.Timestamp)</th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(modelItem => item.Guid)</td> <td>@Html.DisplayFor(modelItem => item.Timestamp)</td> </tr> } </tbody> </table>
As you can see every 10 seconds ExampleGuidService creates new guid.