title: Quartz.net Scheduler.Shutdown(true) not killing jobs
body: <p>I have a running quartz job and terminating my <code>BackgroundService</code>, for some reason despite calling <code>scheduler.Shutdown(true)</code> the job remains running.</p>
  <p>Even when looping through and interrupting jobs, the program closes if before the threads exit.</p>
  <p>Aside from my code below, would i be looking at writing a custom IScheduler to ensure runnings jobs are halted on shutdown?</p>
  <p>This is my <code>IJob</code> Execute method:</p>
  <pre><code>public async Task Execute(IJobExecutionContext context)
  {
      var cancellationToken = context.CancellationToken;
  
      while (cancellationToken.IsCancellationRequested == false)
      {
          // Extension method so we catch TaskCancelled exceptions.
          await TaskDelay.Wait(1000, cancellationToken);
          Console.WriteLine(&quot;keep rollin, rollin, rollin...&quot;);
      }
      Console.WriteLine(&quot;Cleaning up.&quot;);
      await Task.Delay(1000);
      Console.WriteLine(&quot;Really going now.&quot;);
  }
  </code></pre>
  <p>This is my shutdown loop (calling shutdown directly doesn't interrupt any running jobs):</p>
  <pre><code>internal class QuartzHostedService : IHostedService
  {
      // These are set by snipped constructor.
      private readonly IJobSettings jobSettings;
      private readonly ILogger logger;
      private readonly IScheduler scheduler;
  
      private async Task AddJobsToScheduler(CancellationToken cancellationToken = default)
      {
          var schedule = SchedulerBuilder.Create();
  
          var downloadJob = JobBuilder.Create&lt;StreamTickersJob&gt;().Build();
  
          var downloadJobTrigger = TriggerBuilder
              .Create()
              .ForJob(downloadJob)
              .WithDailyTimeIntervalSchedule(
                  x =&gt; x.InTimeZone(serviceTimeZone)
                      .OnEveryDay()
                      .StartingDailyAt(new TimeOfDay(8,0))
                      .EndingDailyAt(new TimeOfDay(9,0)))
              .Build();
  
          await this.scheduler.ScheduleJob(downloadJob, downloadJobTrigger, cancellationToken);
      }
  
      public QuartzHostedService(IJobSettings jobSettings, IScheduler scheduler, ILogger&lt;QuartzHostedService&gt; logger)
      {
          this.jobSettings = jobSettings;
          this.scheduler = scheduler;
          this.logger = logger;
      }
  
      public async Task StartAsync(CancellationToken cancellationToken)
      {
          this.logger.LogInformation(&quot;Quartz started...&quot;);
          await AddJobsToScheduler(cancellationToken);
          await this.scheduler.Start(cancellationToken);
      }
  
      public async Task StopAsync(CancellationToken cancellationToken)
      {
          await this.scheduler.PauseAll(cancellationToken);
  
          foreach (var job in await this.scheduler.GetCurrentlyExecutingJobs(cancellationToken))
          {
              this.logger.LogInformation($&quot;Interrupting job {job.JobDetail}&quot;);
              await this.scheduler.Interrupt(job.JobDetail.Key, cancellationToken);
  
          }
          await this.scheduler.Shutdown(cancellationToken);
      }
  }
  </code></pre>
  <p>I can confirm <code>IHost</code> is not killing my app abruptly (at least not for a couple of seconds test pause) as I set a breakpoint at the end of the main program as below:</p>
  <pre><code>public static void Main(string[] args)
  {
      // Wrap IHost in using statement to ensure disposal within scope.
      using (var host = CreateHostBuilder(args)
                                  .UseSerilog&lt;Settings&gt;(Settings.Name)
                                  .UseConsoleLifetime()
                                  .Build()
                                  .UseSimpleInjector(container))
      {
          // Makes no difference if I shutdown jobs here.
          // var lifetime = container.GetInstance&lt;IHostApplicationLifetime&gt;();            
          // lifetime.ApplicationStarted.Register(async () =&gt; { });
          // lifetime.ApplicationStopping.Register(async () =&gt; { });
  
          var logger = container.GetInstance&lt;ILogger&lt;Program&gt;&gt;();
  
          try
          {
              host.Run();
          }
          catch (Exception ex)
          {
              logger.LogCritical(ex, ex.Message);
          }
  
          // We reach here, whilst Jobs are still running :(
          logger.LogDebug($&quot;Finish {nameof(Main)}().&quot;);
      }
  }
  </code></pre>
  <p>I have also added from what I have found online the below, but still it doenst wait on shutdown:</p>
  <pre><code>var props = new NameValueCollection
  {
      {&quot;quartz.scheduler.interruptJobsOnShutdownWithWait&quot;, &quot;true&quot;},
  };
  
  var scheduler = AsyncContext.Run(async () =&gt; await new StdSchedulerFactory(props).GetScheduler());
  </code></pre>
  <p>My workaround with a delay to allow jobs to terminate below works, but is so dodgy - kindly advise how I can get this working properly without an brittle arbitrary delay:</p>
  <pre><code>public async Task StopAsync(CancellationToken cancellationToken)
  {
      await this.scheduler.PauseAll(cancellationToken);
      foreach (var job in await this.scheduler.GetCurrentlyExecutingJobs(cancellationToken))
      {
          this.logger.LogInformation($&quot;Interrupting job {job.JobDetail}&quot;);
          await this.scheduler.Interrupt(job.JobDetail.Key, cancellationToken);
  
      }
      await Task.Delay(3000);
      await this.scheduler.Shutdown(cancellationToken);
  }
  </code></pre>