如何在 IIS 中优雅地结束 Quartz 3.0.x with ASP.NET Core 2.2 作业?

How to gracefully end a Quartz 3.0.x with ASP.NET Core 2.2 job in IIS?

我正在尝试在 IIS 中优雅地结束 运行 的 Quartz 作业。我的代码如下:

这份工作

    [DisallowConcurrentExecution]
    public class TestJob : IJob
    {
        private ILoggingService Logger { get; }
        private IApplicationLifetime ApplicationLifetime { get; }

        private static object lockHandle = new object();
        private static bool shouldExit = false;

        public TestJob(ILoggingService loggingService, IApplicationLifetime applicationLifetime)
        {
            Logger = loggingService;
            ApplicationLifetime = applicationLifetime;
        }

        public Task Execute(IJobExecutionContext context)
        {
            //TODO: does not seem work
            //context.CancellationToken.Register(() =>
            //{
            //    lock (lockHandle)
            //    {
            //        shouldExit = true;
            //    }
            //});

            return Task.Run(() =>
            {
                //TODO: check
                ApplicationLifetime.ApplicationStopping.Register(() =>
                {
                    lock (lockHandle)
                    {
                        shouldExit = true;
                    }
                });

                try
                {
                    for (int i = 0; i < 10; i ++)
                    {
                        lock (lockHandle)
                        {
                            if (shouldExit)
                            {
                                Logger.LogDebug($"TestJob detected that application is shutting down - exiting");
                                break;
                            }
                        }

                        Logger.LogDebug($"TestJob ran step {i+1}");
                        Thread.Sleep(3000);
                    }
                }
                catch (Exception exc)
                {
                    Logger.LogError(exc, "An error occurred during execution of scheduled job");
                }
            });
        }
    }

Startup.cs

protected void StartJobs(IApplicationBuilder app, IApplicationLifetime lifetime)
{
    var scheduler = app.ApplicationServices.GetService<IScheduler>();
    //TODO: use some config
    QuartzServicesUtilities.StartJob<TestJob>(scheduler, TimeSpan.FromSeconds(60));

    lifetime.ApplicationStarted.Register(() => scheduler.Start());
    lifetime.ApplicationStopping.Register(() => scheduler.Shutdown());
}

private static void ConfigureApplicationLifetime(ILoggingService logger, IApplicationLifetime lifetime)
{
    lifetime.ApplicationStopping.Register(() =>
    {
        logger.LogInfo(null, "Application is stopping...");
    });

    lifetime.ApplicationStopped.Register(() =>
    {
        logger.LogInfo(null, "Application stopped");
    });
}

所以,我已经连接到 ApplicationStopping 以便能够以优雅的方式关闭 Quartz 作业。但是,当 IIS 应用程序池即将结束时,作业突然结束:

我记得在 ASP.NET 中使用 Quartz 2.x 进行了类似的实现:允许 Quartz 作业完成其工作,前提是它们在应用程序池关闭期间设法完成。

问题:如何在 IIS 中使用 ASP.NET Core 2.2 作业优雅地结束 Quartz 3.0.x?

您可以给 true 一个 'scheduler.Shutdown()' 以等待作业完成。这应该会延迟池关闭,直到作业 运行 结束。

lifetime.ApplicationStopping.Register(() => scheduler.Shutdown(true));

您可以阅读更多相关信息 here