asp.net core hosted service sleeps after api inactivity
Asked Answered
S

2

7

I have a hosted service that checks an email account every minute. I also am using MVC with Web API 2.1. In order to get my hosted service to start, I have to "wake it up" by calling API methods. After a period of inactivity from the Web API the hosted service goes to sleep and stops checking the email. It's like it is getting garbage collected. How do I get it to run continuously?

Assistance will be greatly appreciated.

Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info {Title = "CAS API", Version = "v1"});

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            })

            .AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.WithOrigins(Configuration["uiOrigin"])
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            })
            .AddHostedService<EmailReceiverHostedService>()
            .Configure<EmailSettings>(Configuration.GetSection("IncomingMailSettings"))
            .AddSingleton<IEmailProcessor, MailKitProcessor>()
            .AddSingleton<IEmailRepository, EmailRepository>()


          ...

EmailReceiverHostedService.cs:

using CasEmailProcessor.Options;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Threading;
using System.Threading.Tasks;

public class EmailReceiverHostedService : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private readonly Timer _timer;
    private readonly IEmailProcessor _processor;
    private readonly EmailSettings _emailConfig;


    public EmailReceiverHostedService(ILoggerFactory loggerFactory,
        IOptions<EmailSettings> settings,
        IEmailProcessor emailProcessor)
    {
        _logger = loggerFactory.CreateLogger("EmailReceiverHostedService");
        _processor = emailProcessor;
        _emailConfig = settings.Value;
        _timer = new Timer(DoWork, null, Timeout.Infinite, Timeout.Infinite);
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting.");
        StartTimer();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping.");
        StopTimer();

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }

    private void StopTimer()
    {
        _timer?.Change(Timeout.Infinite, 0);
    }
    private void StartTimer() { _timer.Change(TimeSpan.FromSeconds(_emailConfig.TimerIntervalInSeconds), TimeSpan.FromSeconds(_emailConfig.TimerIntervalInSeconds)); }

    private void DoWork(object state)
    {
        StopTimer();
        _processor.Process();
        StartTimer();
    }
}
Somnifacient answered 19/9, 2018 at 16:52 Comment(4)
What are you using to host your API? There may be an idle timeout configured that says if I do not receive any requests in x minutes, shut down to save memoryBreakfront
I am using IIS to hostSomnifacient
In the app pool there is a 20 minute "idle" timeout. I'm going to watch the logs to see if it does timeout after 20 min and then increase the timeout to 40 min. Ultimately, I may need to host the email part in a win service.Somnifacient
You can configure your application to always run, read this article: docs.hangfire.io/en/latest/deployment-to-production/…Tournai
H
12

As you have thought, the root cause is your host can be shut down because of app pool recycle when hosting in IIS. This has been pointed below:

It is important to note that the way you deploy your ASP.NET Core WebHost or .NET Core Host might impact the final solution. For instance, if you deploy your WebHost on IIS or a regular Azure App Service, your host can be shut down because of app pool recycles.

Deployment considerations and takeaways

For a possible workaround, you could try set idle timeout to zero to disable default recycle.

Due to IIS defualt recycle, you may consider the different hosting approcahes:

  • Use a Windows Service

  • Use a Docker Container (Windows Container), but for that, you’d need Windows Server 2016 or later.

  • Use Azure Functions

For your scenario, you could try Host ASP.NET Core in a Windows Service

Hamer answered 20/9, 2018 at 7:22 Comment(0)
R
1

I create task on Windows Event Scheduler to access an URL to wakeup the service.

powershell.exe -command {Invoke-WebRequest http://localhost:8080}

Raye answered 23/1, 2019 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.