Rob
Rob

Reputation: 7217

How to cancel webhost when process is stopping

I've just tried using the async Task Main method in a templated web API (dotnet 5). Here's my boiler plate code:

public class Program
{
    public static async Task Main(string[] args)
    {
        await CreateHostBuilder(args).Build().RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}

I noticed that the RunAsync takes a cancellation token and I'd like that to be based on the application closing.

My question - what's the correct (standard) way to setup a cancellation token here that's linked back to the process shutdown?

I could do something like this:

public static async Task Main(string[] args)
{
    var cts = new CancellationTokenSource();

    AppDomain.CurrentDomain.UnhandledException += (s, e) => { if (e.IsTerminating) cts.Cancel(); };
    AppDomain.CurrentDomain.ProcessExit += (s, e) => cts.Cancel();
    Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); };

    await CreateHostBuilder(args).Build().RunAsync(cts.Token);
}

But wondered if there's a more standard approach that I'm missing.

Thanks for any tips in advance!

Upvotes: 2

Views: 1969

Answers (2)

Rob
Rob

Reputation: 7217

I just found this UseConsoleLifetime() that can be set on the webHost builder:

public class Program
{
    public static async Task Main(string[] args)
    {
        await CreateHostBuilder(args).Build().RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) => 
        Host.CreateDefaultBuilder(args)
            .UseConsoleLifetime()
            .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}

Now Microsoft.Hosting.LifeTime handles the cancellation token for me. Great!

Upvotes: 1

Zdeněk Jel&#237;nek
Zdeněk Jel&#237;nek

Reputation: 2913

.NET host design puts the logic to terminate the application based on external events (e.g. CTRL + C in console app) into an implementation of IHostLifetime interface.

Existing implementations of IHostLifetime include console, windows service and systemd. This is basically what UseWindowsService and UseSystemd extensions register, see e.g. WindowServiceLifetimeHostBuilderExtensions source. The lifetimes implementations typically use IHostApplicationLifetime to shut down the application. The default web host setup includes the console lifetime.

Using this approach, a single application can be configured as a console app, windows service, or use whatever other shutdown triggers required.

It should not be otherwise necessary to register the cancellation listener to any runtime shutdown events such as UnhandledException or ProcessExit as the application process is getting torn down anyway. The hosting concept is a based on Task-based asynchrony, it does not spawn any subsequent processes or similar resources that would stay alive beyond the exit of Main.

For more details, see Web Host and Generic Host documentation pages.

Upvotes: 4

Related Questions