'ShutdownTimeout not working past 4 seconds?

I have been trying to write a simple .net core 3.1 console app that will work with the windows scheduler. Specificially, that it will shutdown gracefully when a user ends the task in the scheduler. The app is using async await to make multiple REST api calls and record results in a database. So when it gets told to exit I want to rundown the list of outstanding tasks before exiting..

I set up the host as follows:

public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureServices((hostContext, services) =>
                    {
                        var configuration = hostContext.Configuration;
                        services.AddHostedService<LoaderService>();

                        // Extend the shutdown delay to allow time for graceful completion.
                        // (ie: allow tasks to complete and their results to ne written to database)
                        services.Configure<HostOptions>(
                                opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(15));

                    })
                    .UseConsoleLifetime();

So I've set the Shutdown timeout to be 15 secs .. however I note that in the LoaderService it only hangs around for 4 seconds before bailing out. I just used a timer to see how long I could stretch it too before it stopped getting as far as the 'gracefully' message, and it just doesn't work for more than 4 secs...

class LoaderService : IHostedService
    {
        private bool pleaseStop;
        private Task BackgroundTask;
        private readonly IHostApplicationLifetime applicationLifetime;

        public LoaderService(IHostApplicationLifetime applicationLifetime)
        {
            this.applicationLifetime = applicationLifetime;
        }

        public Task StartAsync(CancellationToken _)
        {
            Console.WriteLine("Starting service");


            BackgroundTask = Task.Run(async () =>
            {
                string[] args = Environment.GetCommandLineArgs();
                foreach (string item in args)
                {
                    Console.WriteLine($"arg : {item}");
                }

                while (!pleaseStop)
                {
                    await Task.Delay(50);
                }

                Console.WriteLine($"{DateTime.Now} TASK short wait");
                Thread.Sleep(4000);
                Console.WriteLine($"{DateTime.Now} TASK short wait over");

                Console.WriteLine("Background task gracefully stopped");
            });

            return Task.CompletedTask;
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine($"{DateTime.Now} Stopping service");

            pleaseStop = true;

            await BackgroundTask;
            
            Console.WriteLine($"{DateTime.Now} Service stopped");
        }
    }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source