How to keep a hosted service alive in asp net core 3.1?

12,695

Solution 1

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.0&tabs=visual-studio

If you inherit your infinite job service from the BackgroundService class and implement your logic inside a loop and the needed

await Task.Delay(TimeSpan.FromMinutes(x miutes))

the job will run as soon as the application starts without any API call, and stops when the app stops.

 public class MyService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            Console.WriteLine("test");

            //await run job

            await Task.Delay(TimeSpan.FromSeconds(1));
        }
    }

    public override async Task StartAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("start");

        await ExecuteAsync(cancellationToken);
    }

    public override Task StopAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("stop");

        return Task.CompletedTask;
    }
}

Solution 2

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?

Share:
12,695
Admin
Author by

Admin

Updated on June 13, 2022

Comments

  • Admin
    Admin almost 2 years

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