Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply HostOptions.ShutdownTimeout when configuring .NET Core Generic Host?

Tags:

c#

.net-core

I am using the .NET Core Generic Host (not Web Host) to build a Console app that needs a rather lengthy graceful shutdown. From the source code in

aspnet/Hosting/src/Microsoft.Extensions.Hosting/HostOptions

it seems pretty clear that the ShutdownTimeout option can be used to change the shutdown timeout in the cancellation token that is provided as a parameter to ShutdownAsync. By default it is 5 seconds.

However, I can't figure out where and how to write the code to specify this option in the HostBuilder configuration code that you typically put in the Program.cs file.

Can someone post some code that shows how to do this?

like image 566
Jan Hettich Avatar asked Oct 21 '18 11:10

Jan Hettich


People also ask

What is a generic host in .NET Core?

NET Generic Host in ASP.NET Core. The ASP.NET Core templates create a WebApplicationBuilder and WebApplication, which provide a streamlined way to configure and run web applications without a Startup class. For more information on WebApplicationBuilder and WebApplication , see Migrate from ASP.NET Core 5.0 to 6.0.

How do you use IWebHostEnvironment in CS?

In your main program, you can create an application builder and an application. The Environment (as a IWebHostEnvironment ) is available on both objects. var builder = WebApplication. CreateBuilder(args); var environment = builder.

What happens when you call the host CreateDefaultBuilder in the program CS file of an ASP.NET Core application?

CreateDefaultBuilder performs the following tasks: Configures Kestrel server as the web server using the app's hosting configuration providers. For the Kestrel server's default options, see Configure options for the ASP.NET Core Kestrel web server. Sets the content root to the path returned by Directory.

What is Generic host and Web Host in ASP.NET Core?

NET Generic Host, which is a non-web version of the WebHost that runs ASP.NET Core. In ASP.NET Core 3.0 and 3.1, they moved ASP.NET to run on . NET Generic Host instead of the previously used WebHost. The reason is that the WebHost builder was tied more to HTTP requests and worked well for Web applications.


1 Answers

OK, I finally figured it out ... Here's an outline the configuration code in my Program.cs Main function, with most of the items elided, to show where the configuration for HostOptins.ShutdownTimeout goes.

public static async Task Main(string[] args)
{
    var host = new HostBuilder()
        .ConfigureHostConfiguration(configHost => {...})
        .ConfigureAppConfiguration((hostContext, configApp) => {...})
        .ConfigureServices((hostContext, services) =>
        {
           services.AddHostedService<ApplicationLifetime>();          
           ...
           services.Configure<HostOptions>(
                opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(10));
        })
        .ConfigureLogging(...)
        .UseConsoleLifetime()
        .Build();

    try
    {
        await host.RunAsync();
    }
    catch(OperationCanceledException)
    {
        ; // suppress
    }
}

To make the this work, here is the StopAsync method in my IHostedService class:

public async Task StopAsync(CancellationToken cancellationToken)
{
    try
    {
        await Task.Delay(Timeout.Infinite, cancellationToken);
    }
    catch(TaskCanceledException)
    {
        _logger.LogDebug("TaskCanceledException in StopAsync");
        // do not rethrow
    }
}

See Graceful shutdown with Generic Host in .NET Core 2.1 for more details about this.

Btw, the catch block in Program.Main is necessary to avoid an unhandled exception, even though I am catching the exception generated by awaiting the cancellation token in StopAsync; because it seems that an unhandled OperationCanceledException is also generated at expiration of the shutdown timeout by the framework-internal version of StopAsync.

like image 75
Jan Hettich Avatar answered Oct 13 '22 01:10

Jan Hettich