With the release of Net Core 3. The Asp.Net team introduced a new template for building background applications called Worker Service, which is available as part of the SDK. Worker Services are designed to do background work, and the main feature of Worker Service is that unlike IIS programs, which are suspended after a while if a request is not sent to the program, Worker Services will always be active like Windows services. And they do things on a specific schedule. In this article, we will implement a Worker Service and publish it and introduce it as a Windows service. To create a project in Visual Studio, select Worker Service from among the projects and create a project called WorkerServiceExample. Then a class called Worker should be created like this:
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);
}
}
}
The ExecuteAsync method is executed once and stays inside the while loop until the CancellationToken value is true and does the required work. The ExecuteAsync method runs after the StartAsync method. And after finishing the work, after the ExecuteAsync method, the StopAsync method is executed. StopAsync and StartAsync methods are created in the BackgroundService class and you can override these two methods and do a series of tasks depending on your needs. Although you can not override these methods, you must implement the ExecuteAsync method because abstract Being a method. If you run the program, a message is displayed in the console every second, as follows:
info: WorkerServiceExample.Worker[0]
Worker running at: 10/09/2020 20:35:00 +03:30
info: WorkerServiceExample.Worker[0]
Worker running at: 10/09/2020 20:35:01 +03:30
info: WorkerServiceExample.Worker[0]
Worker running at: 10/09/2020 20:35:02 +03:30
info: WorkerServiceExample.Worker[0]
Worker running at: 10/09/2020 20:35:03 +03:30
In Worker Services, it is not possible to receive registered services of Scoped type normally, but you can register your services of singleton and transient type and receive them from DI, and if you want a registered service of Scoped type from DI Get you must use IServiceProvider. Next, we create a service and introduce the service as Scoped to DI, and then introduce Worker Service as a service to Windows services. First we create an interface called ISomeService and a class that inherits from the interface and implements its methods.
public interface ISomeService
{
Task DoSomething(CancellationToken cancellationToken);
}
public class SomeService : ISomeService
{
private readonly ILogger<SomeService> _logger;
public SomeService(ILogger<SomeService> logger)
{
_logger = logger;
}
public async Task DoSomething(CancellationToken cancellationToken)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.CompletedTask;
}
}
Then we register this service as Scoped to DI in the Program.cs class
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>();
services.AddScoped<ISomeService, SomeService>();//<--NOTE THIS
});
}
Next, to use the ISomeService service in the Worker class, we must first get the IServiceProvider from the DI and create a scope in the ExecuteAsync method, and then get the service we need, which is registered as Scoped, and call the DoSomething method.
public class Worker : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
public Worker(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using(var scope = _serviceProvider.CreateScope())
{
var someService = scope.ServiceProvider.GetRequiredService<ISomeService>();
await someService.DoSomething(stoppingToken);
}
await Task.Delay(1000, stoppingToken);
}
}
}
Now, if you run the program, it will not see any difference from before to get things done. Although there was no need to register a Scoped service in this project, the only purpose was to get the Scoped services registered in the Worker Service. If you register the same ISomeService service as Transient, you can get the service you need directly from the DI within the Worker class constructor and call the DoSomething method, and you do not need to get the IServiceProvider and create a scope. Next, to publish the project and introduce it to Windows services, you must install the Microsoft.Extensions.Hosting.WindowsServices package and add the UseWindowsService command in the Program.cs class.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
services.AddScoped<ISomeService, SomeService>();
})
.UseWindowsService();
Then get a publisher of the project and run powershell publisher through the admin in the path of the created files and just run the following command:
sc.exe create WorkerServiceExample binPath="C:\Users\Farhad\source\repos\WorkerServiceExample\WorkerServiceExample\bin\Release\netcoreapp3.1\publish\WorkerServiceExample.exe"
Note that you must enter the full path of the exe file to powershell. This command runs a service called WorkerServiceExample on Windows services. The service has now been created but is Stop. To run the service, just run the following command:
sc.exe start WorkerServiceExample
Whenever you want to stop or delete the desired service, you can execute the following commands:
sc.exe delete WorkerServiceExample
And
sc.exe stop WorkerServiceExample
;)
Powered by Froala Editor