How to work with worker services in ASP.NET Core

Learn how to use the new template available in ASP.NET Core 3.0 to build a worker service.

connected workers
Thinkstock

ASP.NET Core 3.0 Preview 3 adds support for creating worker services, which are background services like Windows services and Linux daemons. There is a new template for creating a worker service in Visual Studio as well.

To work with worker services in Visual Studio, you should have the beta versions (Preview Version 3 or later) of ASP.NET Core 3.0 and .NET Core 3.0 runtimes installed on your system.

Create a new worker service application

First, let’s create an ASP.NET Core project in Visual Studio 2019. Follow these steps o create a new ASP.NET Core project in Visual Studio:

  1. Launch the Visual Studio IDE.
  2. Click Create New Project.
  3. In the Create New Project window, select ASP.NET Core Web Application from the list of templates.
  4. Click Next.
  5. In the Configure Your New Project window that appears, specify the name and location for the new project.
  6. Click Create.
  7. The window Create New ASP.NET Core Web Application appears.
  8. Select .NET Core as the runtime and ASP.NET Core 3.0 (or later) from the dropdown menu at the top.
  9. Select Worker Service as the project template to create a new worker service application
  10. Ensure that the check box Enable Docker Support is unchecked, because you won’t be using this feature here.
  11. Ensure that Authentication is set as No Authentication, because you won’t be using authentication either.
  12. Click Create.

This creates a new worker service application in Visual Studio.

worker service 1 IDG

A new worker service in ASP.NET Core.

The Program class

The default implementation of the worker service contains two classes: the Program and Worker classes. The Program class is like the one you have in web applications, with the difference that instead of a Startup class, you have a Worker class. Here’s what the Program class looks like. Note how the AddHostedService method is used.

    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>();
                });
    }

The Worker class

The Worker class provides support for dependency injection. The Worker service class extends the BackgroundService class in the Microsost.Extensions.Hosting.Abstractions package. The BackroundService abstract class extends the IHostedService interface and contains the declarations of the StartAsync, StopAsync, and ExecuteAsync methods.

public abstract class BackgroundService : IHostedService, IDisposable
{
    public virtual void Dispose();
    public virtual Task StartAsync(CancellationToken cancellationToken);
    public virtual Task StopAsync(CancellationToken cancellationToken);
    protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
}

The constructor of the Worker class accepts an instance of type ILogger as an argument. The following code snippet shows the default implementation of the Worker class:

   public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }
        protected override async Task ExecuteAsync
        (CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation
                 ("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
worker service 2 IDG

You can run the worker service as an .exe file from Visual Studio or even as a Windows service. To run worker service as a Windows service, you should add the Microsoft.Extensions.Hosting.WindowsServices NuGet package to your project.

You can run the worker service much the same way you run applications in Visual Studio: by pressing F5 or Ctrl+F5. When you run the minimalistic worker service, the figure shows what the output looks like.

Extend the default worker service

You can override the methods of the BackgroundService abstract class to add more functionality to the worker service. You can override the ExecuteAsync method to write the code for performing any long running tasks. The following code shows the enhanced version of the Worker class; the StartAsync, ExecuteAsync, and StopAsync methods have been implemented.

   public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }
        public override Task StartAsync(CancellationToken
         cancellationToken)
        {
            _logger.LogInformation
            ("Worker service has been started at: {0}", DateTime.Now);
            return base.StartAsync(cancellationToken);
        }
        protected override Task ExecuteAsync(CancellationToken
         stoppingToken)
        {
            _logger.LogInformation
            ("Worker service running at: {0}", DateTime.Now);
            return Task.CompletedTask;
        }
        public override Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation
            ("Worker service has been stopped at: {0}", DateTime.Now);
            return base.StopAsync(cancellationToken);
        }
        public override void Dispose()
        {
            _logger.LogInformation
            ("Worker service has been disposed at: {0}", DateTime.Now);
            base.Dispose();
        }
    } 

Log data in the worker service

To use logging in your worker service, you should add a reference to the Microsoft.Extensions.Logging assembly. The default logger in a worker service is ConsoleLogger. You can also use EventLog as the log target in your worker service. To use EventLog as the log target, add the Microsoft.Extensions.Logging.EventLog NuGet package to your project.

The following code snippet illustrates how you can configure the logging output to event log in the CreateHostBuilder method of the Program class:

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

Copyright © 2019 IDG Communications, Inc.