What is the equivalent to the ServiceBase.RequestAdditionalTime in .net core using a BackgroundService?
Asked Answered
S

0

11

In our .NET framework services, we always request additional time from the service control manager when our services start to give them more time to start than the default (30 seconds?) before reporting that they haven't started.

We do this using the RequestAdditionalTime method of the ServiceBase class, e.g.

protected override void OnStart(string[] args)
{
    RequestAdditionalTime(120 * 1000);
    // Do stuff.
}

We do this because we check some stuff like version compatibility with the SQL database runnning in SQL Server before starting any of the other threads etc in case the service should not start. What we found was that SQL Server was not always running in time for the service to connect to it at startup so we ask that the service control manager gives the service more time to start up so that we can retry database connection.

I want to do the same with our .NET core 3 services but can't find any equivalent way to request additional time from the service control manager. So if we have a BackgroundService that we've configured with UseWindowsService() in the host builder, how do I get to request more time like we do with .NET Framework?

public class Worker : BackgroundService
    {
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            CheckDatabaseCompatibility();

            while (!stoppingToken.IsCancellationRequested)
            {
                // Do stuff.
            }
        }
}

We're using .NET Core 3.1.1 and running the exe as a service in Windows.

Sapsago answered 30/1, 2020 at 14:3 Comment(7)
There appears to be a way to configure additional time for shutdown by using ShutdownTimeout in the HostOptions when configuring services, but nothing for startup.Sapsago
ExecuteAsync does not work the same as OnStart. With ExecuteAsync it is generated as a Task and does not need to return timely in the way that OnStart does. What issue are you actually experiencing? If you have implemented multiple IHostedService then you might have the issue that CheckDatabaseCompatibility will block any other HostedServices from executing until the first async call is made. Further reading here: learn.microsoft.com/en-us/aspnet/core/fundamentals/host/…Norenenorfleet
The issue is that the initial database compatibility checks might take some time (it might have to wait for SQL Server to start up after boot). The time it waits before saying it failed to check or the check failed is way longer than the default time it waits for a service to start before it claims it as a failure. The service must not be allowed to do anything else until the compatibility has been checked (succeeded or failed).Sapsago
ExecuteAsync of a BackgroundService does not block service startup. That is why you can have a forever running while loop within ExecuteAsync. So it does not matter how long CheckDatabaseCompatibility takes to run as you could literally do a Thread.Sleep in ExecuteAsync and that will not make the service start timeout.Norenenorfleet
What about if this code was in StartAsync rather than ExecuteAsync?Sapsago
Quick test with StartAsync sleeping for 90 seconds and the service started fine. Not sure if you have tried this code but I think the problem you are used to from classic framework/service OnStart is not the same. If you want to, but not sure why you would, you could RequestAdditionalTime additional time via something like: github.com/aspnet/Hosting/blob/master/samples/GenericHostSample/… but the point is you should not need to because that defeats the cross platform functionality of .net core.Norenenorfleet
Possibly related: github.com/dotnet/aspnetcore/issues/22994Marylnmarylou

© 2022 - 2024 — McMap. All rights reserved.