Worker Service in .NET Core 3.1
Tags: dotnet, webdev, csharp
Published: 2020-06-21 22:00:57

---
title: Worker Service in .NET Core 3.1
published: true
date: 2020-06-17 14:00:00 UTC
tags: dotnet, webdev, csharp 
canonical_url: https://wakeupandcode.com/worker-service-in-net-core-3-1/
---

![](https://wakeupandcode.com/wp-content/uploads/2020/01/aspnetcore-az-banner.png)

This is the twenty-third of a new [series of posts](https://wakeupandcode.com/aspnetcore/#aspnetcore2020) on ASP .NET Core 3.1 for 2020. In this series, we’ll cover 26 topics over a span of 26 weeks from January through June 2020, titled  **ASP .NET Core A-Z!**  To differentiate from the [2019 series](https://wakeupandcode.com/aspnetcore/#aspnetcore2019), the 2020 series will mostly focus on a growing single codebase ([NetLearner!](https://wakeupandcode.com/netlearner-on-asp-net-core-3-1/)) instead of new unrelated code snippets week.

Previous post:

- [Validation in ASP .NET Core 3.1](https://wakeupandcode.com/validation-in-asp-net-core-3-1/)

**NetLearner on GitHub** :

- Repository: [https://github.com/shahedc/NetLearnerApp](https://github.com/shahedc/NetLearnerApp)
- v0.23-alpha release: [https://github.com/shahedc/NetLearnerApp/releases/tag/v0.23-alpha](https://github.com/shahedc/NetLearnerApp/releases/tag/v0.23-alpha)

**NOTE** : The Worker Service sample is a meta project that generates Word documents from blog posts, to auto-generate an ebook from this blog series. You can check out the code in the following experimental subfolder, merged from a [branch](https://github.com/shahedc/NetLearnerApp/tree/WorkerService/experimental/DocMaker):

- Doc Maker: [https://github.com/shahedc/NetLearnerApp/tree/master/experimental/DocMaker](https://github.com/shahedc/NetLearnerApp/tree/master/experimental/DocMaker) 

# In this Article:

- [W is for Worker Service](#W)
- [New Worker Service Project](#project)
- [Program and BackgroundService](#program)
- [Logging in a Worker Service](#logging)
- [Running the Worker Service](#service)
- [References](#refs)

# W is for Worker Service

When you think of ASP .NET Core, you probably think of web application backend code, including MVC and Web API. MVC Views and Razor Pages also allow you to use backend code to generate frontend UI with HTML elements. The all-new Blazor goes one step further to allow client-side .NET code to run in a web browser, using WebAssembly. And finally, we now have a template for Worker Service applications.

Released with ASP .NET Core 3.0, the new project type was introduced in ASP .NET Core early previews. Although the project template was initially listed under the Web templates, it has since been relocated one level up in the New Project wizard. This is a great way to create potentially long-running cross-platform services in .NET Core. This article covers the Windows operating system.

![](https://wakeupandcode.com/wp-content/uploads/2020/06/worker-diagram-1024x427.png)<figcaption>Cross-platform .NET Core Worker Service</figcaption>

# New Worker Service Project

The quickest way to create a new Worker Service project in Visual Studio 2019 is to use the latest template available with .NET Core 3.1. You may also use the appropriate dotnet CLI command.

Launch Visual Studio and select the Worker service template as shown below. After selecting the location, verify the version number (e.g. .NET Core 3.1) to create the worker service project.

![](https://wakeupandcode.com/wp-content/uploads/2020/06/worker-vs2019-new-project-1024x710.png)<figcaption>Worker Service template in Visual Studio 2019</figcaption>

![](https://wakeupandcode.com/wp-content/uploads/2020/06/worker-vs2019-create-project-1024x710.png)<figcaption>Worker Service on .NET Core 3.1</figcaption>

To use the Command Line, simply use the following command:

```
> **dotnet** new worker -o _myproject_
```

where -o is an optional flag to provide the output folder name for the project.

You can learn more about this template at the following location:

- Worker Service template:  [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio#worker-service-template](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio#worker-service-template) 

# Program and BackgroundService

The [Program.cs](https://github.com/shahedc/NetLearnerApp/blob/master/experimental/DocMaker/Program.cs) class contains the usual **Main()** method and a familiar **CreateHostBuilder()** method. This can be seen in the snippet below:

```
public class **Program** { public static void **Main** (string[] args) { **CreateHostBuilder** (args).Build().Run(); } public static IHostBuilder **CreateHostBuilder** (string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices(hostContext, services => { services. **AddHostedService** <Worker>(); }); }
```

Things to note:

1. The Main method calls the  **CreateHostBuilder** () method with any passed parameters, builds it and runs it.
2. As of ASP .NET Core 3.0, the _Web_ Host Builder has been replaced by a _Generic_ Host Builder. The so-called Generic Host Builder was covered in an [earlier blog post](https://wakeupandcode.com/generic-host-builder-in-asp-net-core-3-1/#generic31) in this series.
3. **CreateHostBuilder** () creates the host and configures it by calling  **AddHostService** <T>, where T is an  **IHostedService** , e.g. a worker class that is a child of  **BackgroundService**

The worker class, [Worker.cs](https://github.com/shahedc/NetLearnerApp/blob/master/experimental/DocMaker/Worker.cs), is defined as shown below:

```
public class **Worker** : **BackgroundService** { // ... protected override async Task **ExecuteAsync** (CancellationToken stoppingToken) { // do stuff here }}
```

Things to note:

1. The worker class implements the  **BackgroundService**  class, which comes from the namespace Microsoft.Extensions.Hosting
2. The worker class can then override the **ExecuteAsync()** method to perform any long-running tasks.

In the sample project, a utility class ([DocEngine.cs](https://github.com/shahedc/NetLearnerApp/blob/master/experimental/DocMaker/Utils/DocEngine.cs)) is used to convert a web page (e.g. a blog post or article) into a Word document for offline viewing. Fun fact: when this A-Z series wraps up, the blog posts will be assembled into a free ebook, by using this DocMaker, which uses some 3rd-party NuGet packages to generate the Word document.

# Logging in a Worker Service

Logging in ASP .NET Core has been covered in great detail in an earlier blog post in this series. To get a recap, take a look at the following writeup:

- Logging in ASP .NET Core 3.1: [https://wakeupandcode.com/logging-in-asp-net-core-3-1/](https://wakeupandcode.com/logging-in-asp-net-core-3-1/)

To use Logging in your Worker Service project, you may use the following code in your [Program.cs](https://github.com/shahedc/NetLearnerApp/blob/master/experimental/DocMaker/Program.cs) class:

```
using Microsoft.Extensions.Logging;

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) . **ConfigureLogging** (**loggerFactory => loggerFactory.AddEventLog()**) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); });
```

1. Before using the extension method, add its NuGet package to your project:
  - Microsoft.Extensions.Logging.EventLog
2. Add the appropriate namespace to your code:
  - using Microsoft.Extensions.Logging;
3. Call the method  **ConfigureLogging** () and call the appropriate logging method, e.g.  **AddEventLog** ()

The list of available loggers include:

- AddConsole()
- AddDebug()
- AddEventLog()
- AddEventSourceLogger()

The [Worker class ](https://github.com/shahedc/NetLearnerApp/blob/master/experimental/DocMaker/Worker.cs)can then accept an injected  **ILogger<Worker> ** object in its constructor:

```
private readonly **ILogger** < **Worker** > **\_logger** ;public Worker( **ILogger<Worker> logger** ){ **\_logger = logger;** }
```

# Running the Worker Service

**NOTE** : Run Powershell in Administrator Mode before running the commands below.

Before you continue, add a call to  **UseWindowsService** () in your [Program class](https://github.com/shahedc/WorkerServiceSample/blob/master/WorkerServiceSample/Program.cs), or verify that it’s already there. To call UseWindowsService(), the following package must be installed in your project: [Microsoft.Extensions.Hosting.WindowsServices](https://www.nuget.org/packages/Microsoft.Extensions.Hosting.WindowsServices)

The official announcement and initial document referred to  **UseServiceBaseLifetime** () in an earlier preview. This method was renamed to  **UseWindowsService** () before release.

```
   public static IHostBuilder **CreateHostBuilder** (string[] args) => Host.CreateDefaultBuilder(args) . **UseWindowsService** () .ConfigureServices(hostContext, services => { services.AddHostedService<Worker>(); });
```

According to the code documentation,  **UseWindowsService** () does the following:

1. Sets the host lifetime to WindowsServiceLifetime
2. Sets the Content Root
3. Enables logging to the event log with the application name as the default source name

You can run the Worker Service in various ways:

1. Build and Debug/Run from within Visual Studio.
2. Publish to an exe file and run it
3. Run the sc utility (from Windows\System32) to create a new service

To publish the Worker Service as an exe file with dependencies, run the following  **dotnet**  command:

```
**dotnet publish** -o C:\path\to\project\pubfolder
```

The -o parameter can be used to specify the path to a folder where you wish to generate the published files. It could be the path to your project folder, followed by a new subfolder name to hold your published files, e.g. pubfolder. Make a note of your EXE name, e.g. MyProjectName.exe but omit the pubfolder from your source control system.

To create a new service, run  **sc.exe**  from your System32 folder and pass in the name of the EXE file generated from the publish command.

```
> **C:\Windows\System32\sc** create MyServiceName binPath=C:\path\to\project\pubfolder\MyProjectName.exe
```

When running the sample manually, you should see some logging messages, as shown below:

```
info: DocMaker.Worker[0] **Making doc 1 at: 06/09/2020 00:09:52 -04:00**** Making your document...**info: DocMaker.Worker[0]**Making doc 2 at: 06/09/2020 00:10:05 -04:00 ****Making your document...**
```

After the service is installed, it should show up in the operating system’s list of Windows Services:

![](https://wakeupandcode.com/wp-content/uploads/2020/06/worker-services-1024x424.png)<figcaption>Windows Services, showing custom Worker Service</figcaption>

**NOTE** : When porting to other operating systems, the call to  **UseWindowsService** () is safe to leave as is. It doesn’t do anything on a non-Windows system.

# References

- .NET Core Workers as Windows Services: [https://devblogs.microsoft.com/aspnet/net-core-workers-as-windows-services/](https://devblogs.microsoft.com/aspnet/net-core-workers-as-windows-services/?WT.mc_id=-blog-shchowd)
- Worker Service template in .NET Core 3.0: [https://gunnarpeipman.com/dotnet-core-worker-service/](https://gunnarpeipman.com/dotnet-core-worker-service/)
- Worker Service Template in .NET Core 3.0 – DZone Web Dev: [https://dzone.com/articles/worker-service-template-in-net-core-30](https://dzone.com/articles/worker-service-template-in-net-core-30)
- .NET Core Workers in Azure Container Instances: [https://devblogs.microsoft.com/aspnet/dotnet-core-workers-in-azure-container-instances/](https://devblogs.microsoft.com/aspnet/dotnet-core-workers-in-azure-container-instances/?WT.mc_id=-blog-shchowd)
- Background tasks with hosted services: [https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services)