I've implemented IHostedService in an asp.net core website. It works great but the problem is that I want it to be started when the hosting server boots up or the IIS service restarts but it won't unless the first request to the website comes in.
UPDATE 1: "Application Initialization Module", Suggested by @Arthur did not help. Neither on site nor server level.
The configuration I used:
<applicationInitialization
doAppInitAfterRestart="true"
skipManagedModules="false"
remapManagedRequestsTo="init.htm">
<add initializationPage="/init.htm" hostName="localhost"/>
</applicationInitialization>
UPDATE 2: Here is how I implemented the interface
internal class PaymentQueueService : IHostedService, IDisposable
{
private readonly ILogger _logService;
private Timer _timerEnqueue;
public PaymentQueueService(ILogger logService)
{
_logService = logService;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logService.LogInformation("Starting processing payments.");
_timerEnqueue = new Timer(EnqueuePayments, null, TimeSpan.Zero,
TimeSpan.FromSeconds(10));
return Task.CompletedTask;
}
private void EnqueuePayments(object state)
{
_logService.LogInformation("Enqueueing Payments.");
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logService.LogInformation("Stopping processing payments.");
_timerEnqueue?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timerEnqueue?.Dispose();
}
}
The Program class in main.cs file:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args).ConfigureServices(services =>
{
services.AddHostedService<PaymentQueueService>();
}).Configure((IApplicationBuilder app) =>
{
app.UseMvc();
})
.UseStartup<Startup>();
}
The Startup class:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
}
}
Since the suggested "Application Initialization Module" did not work, you could consider making the call yourself with a client since
The module starts the process for the ASP.NET Core app when the first request arrives and restarts the app if it shuts down or crashes.
public class Program {
static Lazy<HttpClient> client = new Lazy<HttpClient>();
public static async Task Main(string[] args) {
var host = CreateWebHostBuilder(args).Start();//non blocking start
using (host) {
bool started = false;
do {
var response = await client.Value.GetAsync("site root");
started = response.IsSuccessStatusCode;
await Task.Delay(someDelayHere);
} while (!started);
host.WaitForShutdown();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services => {
services.AddHostedService<PaymentQueueService>();
})
.Configure((IApplicationBuilder app) => {
app.UseMvc();
})
.UseStartup<Startup>();
}
NOTE:
To prevent apps hosted out-of-process from timing out, use either of the following approaches:
- Ping the app from an external service in order to keep it running.
- If the app only hosts background services, avoid IIS hosting and use a Windows Service to host the ASP.NET Core app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With