Joydip Kanjilal
Contributor

How to work with worker services in ASP.NET Core

how-to
Aug 19, 20195 mins
Microsoft .NETSoftware Development

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

connected workers
Credit: 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>();
        }); 
Joydip Kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author