C# – How to keep a hosted service alive in asp net core 3.1

asp.net-coreasp.net-core-3.0asp.net-core-webapic

how are you?.

I have a web api in net core 3.1, this in turn contains a service that every X minutes has to run to perform data migrations (I'm just testing it), but I have 2 problems.

  1. For the service to run, I must first run some url of my apis. The question is: How can I make this service start automatically, without the need to run any api?
  2. When I stop using the apis for a few minutes, the service stops working. The question is: How can I keep the service "Forever" alive?

I must emphasize that my web api is hosted in a web hosting, where I do not have access to all the features of IIS

This is my code, and in advance I appreciate your help.

MySuperService.cs

 public class MySuperService : IHostedService, IDisposable
{
    private bool _stopping;
    private Task _backgroundTask;
    private static readonly log4net.ILog log =log4net.LogManager.GetLogger(typeof(MySuperService));
    public Task StartAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("MySuperService is starting.");
        log.Info("MySuperService is starting.");
        _backgroundTask = BackgroundTask();
        return Task.CompletedTask;
    }

    private async Task BackgroundTask()
    {
        int contador = 1;
        while (!_stopping)
        {
            Console.WriteLine("MySuperService is working--> " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            log.Info("MySuperService is working--> " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            await Task.Delay(TimeSpan.FromMinutes(3));
            contador++;
        }

        Console.WriteLine("MySuperService background task is stopping.");
        log.Info("MySuperService background task is stopping.");
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("MySuperService is stopping.");
        log.Info("MySuperService is stopping.");
        _stopping = true;
        if (_backgroundTask != null)
        {
            // TODO: cancellation
            await BackgroundTask();
            //await _backgroundTask;
        }
    }

    public void Dispose()
    {
        Console.WriteLine("MySuperService is disposing.");
        log.Info("MySuperService is disposing.");
    }
}

Program.cs

public class Program
{
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
    public static void Main(string[] args)
    {
        ...
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            }).ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<MySuperService>();
            });
}

Best Answer

Inherit from BackgroundService instead of implemented IHostedService. That will take care of the machinery of starting, running and stopping your service for you.

However the problem you are facing is that IIS isn't starting your c# process until the first request of the service. Then the default application pool settings will shut it down again if there are no requests. I'd suggest setting up some kind of scheduled task to periodically request a url and monitor that the service is running. You'll want to be notified if it stops anyway right?