In a .NET 6 Web application I added a Quartz Job to run a daily task. The quartz job is added using .AddQuartz and .AddQuartzHostedService as shown on https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/hosted-services-integration.html#installation page
What can I do to make the Quartz Scheduler/Jobs start when the application pool starts?
Quartz does start running correctly after the first web request is made to the application. In IIS I have set the AppPools Start Mode to AlwaysRunning,the .NET CLR Version to both No Managed Code or v4.0. I installed Application Initialization on the web server and set the applications Preload Enabled property to True.
When IIS starts up, a w3wp.exe task starts using the application pools AD identity. After the first web request, a new conhost.exe task starts on the web server also using the application pools AD identity which I assume is the Quartz scheduler running. I checked the Event Viewer for errors and I am not finding anything that appears to be related to this issue.
This is the Program.cs of the web app.
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.EntityFrameworkCore;
using DataChecker_3186.Data;
using DataChecker_3186.Models;
using Quartz;
using DataChecker_3186.IdmsInterface;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddDbContext<FitProContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("FitProContext")));
builder.Services.AddDbContext<HITSContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("HITSContext")));
builder.Services.AddScoped<ILookupLists, LookupLists>();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddTransient<IIdmsService, IdmsService>();
var sendJobKey = new JobKey("SendToIdms");
var watchJobKey = new JobKey("MonitorIdmsOutput");
var sendToIdmsCron = builder.Configuration.GetValue<string>("IdmsInterfaceSettings:SendToIdmsCron");
var monitorIdmsOutputCron = builder.Configuration.GetValue<string>("IdmsInterfaceSettings:MonitorIdmsOutputCron");
builder.Services.AddQuartz(q =>
{
q.SchedulerId = "MaskFitRecordsJobScheduler";
q.SchedulerName = "MaskFitRecords Job Scheduler";
q.UseMicrosoftDependencyInjectionJobFactory();
q.AddJob<SendToIdmsJob>(opts => opts.WithIdentity(sendJobKey));
q.AddJob<ProcessIdmsOutput>(opts => opts.WithIdentity(watchJobKey));
q.AddTrigger(opts => opts
.WithIdentity(sendJobKey.Name + "-trigger")
.ForJob(sendJobKey)
.StartNow()
.WithCronSchedule(sendToIdmsCron));
q.AddTrigger(opts => opts
.ForJob(watchJobKey)
.WithIdentity(watchJobKey.Name + "-trigger")
.WithCronSchedule(monitorIdmsOutputCron));
});
builder.Services.AddTransient<SendToIdmsJob>();
builder.Services.AddTransient<ProcessIdmsOutput>();
builder.Services.AddQuartzHostedService(q =>
{
q.WaitForJobsToComplete = true;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=FitTests}/{action=Index}/{id?}");
app.Run();