Skip to main content

Building Cross-Platform Worker Services with .NET Core

If you have been in software development long enough, at some point you must have come across a need to have a long running background service. This came in the form of either windows services or daemons (for non windows systems).

With the release of .NET Core 3.0, there is a new type of application template which was introduced to address the need of building cross-platform worker services. This could either be a Windows service or a systemd process that runs on Linux.

You can either create the worker service using the Visual studio template as below
Or use the command line and run command dotnet new worker
The created project has the below file structure
Program.cs is the entry point for the application that registers and builds the host. Worker.cs file contains default worker. It inherits from  Microsoft.Extensions.Hosting.BackgroundService class and overrides the ExecuteAsync method.

Below is the Worker.cs code

The code in ExecuteAsync method logs information into the console every-time the method is invoked. In this case the worker executes every 1 sec (1000 milliseconds) because of the Task.Delay async call. The method also accepts a CancellationToken that allows cooperative cancellation between threads, thread pool work items, or Task objects.

In addition to this there are several other methods which we can override to run a piece of logic at different stages of the worker life-cycle. In order to demonstrate this, I have added the StartAsync and StopAsync methods that run when the host is ready to start or stop the service.

If we now run the application, messages are logged to the console continuously based on the delay interval, as below.

Notice the messages printed out from the StartAsync and StopAsync methods.

Run as Windows Service
To run the project as a windows service, we need to add the Microsoft.Extensions.Hosting.WindowsServices package to our project. This can either be done by right-clicking on the project and "Manage NuGet Packages..." or by running the below command using the package manager console window.

Install-Package Microsoft.Extensions.Hosting.WindowsServices

Once the package is installed, Add the UseWindowsService() call to the host builder.

In order to install as windows service we first have to publish the app. This can be done by either right-clicking the project and selecting Publish or by running the below command.
dotnet publish -o c:\repo\workerpub

Next use the sc utility in an admin console prompt to run the below command.
sc create workertest binPath=c:\repo\workerpub\Worker.exe

Run as Linux Daemon
Add package Microsoft.Extensions.Hosting.Systemd. Then add User  UseSystemd()  call to the host builder.

Set up as daemon in Linux

As you can see it's pretty easy to create a create and run a worker service. Also the advantage is that the same code base can be used to run as a windows service or a daemon.

In addition to all of this .NET core worker service comes with built in Logging, Dependency Injection and Configuration support.