Generic Host
Console apps or ASP.NET Core background tasks can use IHostedService
to run.
Such apps are also perfect to run in:
- containers
- system services (e.g. via systemd)
IHostedService
StartAsync
The StartAsync
method of the IHostedService
interface is async, but it’s run
inline during startup. If the hosted service is a long-running one, it should
return a Task
immediately and schedule the work on a separate thread. Using
await
is also not recommended.
BackgroundService
The BackgroundService
is a convenient base class. It’s designed to be used
with long-running tasks. It has just one method to override - ExecuteAsync()
.
We can freely use await
and never-ending loops (although we should be checking
CancellationToken
).
HttpClient and other non-singleton services
If our IHostedService
implementation is long-lived we shouldn’t inject HTTP
services there (e.g. typed HttpClients). HttpClient
should be short-lived. We
could either use IServiceProvider
to get new typed client in some interval
(service locator - not ideal) or use IHttpClientFactory
.
Terminating the app
The hosted service can terminate the app when finished the execution. An
instance of IHostApplicationLifetime
needs to be injected and used:
Worker Service
Worker Service is a console app without the ASP.NET Core stuff.
We can easily create a Worker Service project with dotnet new worker
. It
creates a simple Worker
class that inherits from BackgroundService
and
Program.cs
that sets up IHost
.
To get access to IHttpCLientFactory
we need to add the
Microsoft.Extensions.Http
NuGet package.
Systemd
To turn an app into a systemd service, we’d install the
Microsoft.Extensions.Hosting.Systemd
package. Then we’d call the
UseSystemd()
method on IHostBuilder
.
Quartz.NET
Quartz.NET is a scheduler library that enable some more advanced features of background services, like:
- CRON
- running multiple instances of it, with options to control concurrency (similar to RedLock)
It acts as a
Manual Creation
We can also create the boilerplate manually.
Imports
Creating an IHostBuilder
Simple:
With configuration:
Running the application
.NET 6: