I have an app that I need to clean up some resources before it shuts down. I've got it handling the event using:
AppDomain.CurrentDomain.ProcessExit = OnProcessExit;
private static async void OnProcessExit(object? sender, EventArgs e)
{
Console.WriteLine("We");
Thread.Sleep(1000);
Console.WriteLine("Are");
Thread.Sleep(1000);
Console.WriteLine("Closing");
}
But the event never gets fired? At least I don't see it, it instantly closes. I've tried this in an external and internal console and neither seem to catch it.
Using Linux Ubuntu 20.10
CodePudding user response:
Normally you should use AppDomain.ProcessExit
rather than AppDomain.CurrentDomain.ProcessExit
. Is there a specific reason why you're using the second form?
How is your console app closing? Is it a normal exit after finishing its work, or failing due to an unmanaged exception, or dying due to a rude shutdown (eg Ctrl-C
, Environment.FailFast
, etc)?
In the first two cases AppDomain.ProcessExit
should be invoked normally. But if that isn't happening for some reason, you can use Try..Finally
to do resource cleanup.
In the third case, it's very likely that AppDomain.ProcessExit
won't be invoked. And there's not a lot you can do about that.
Are you using a Debug or Release build? Because shutdown behaviour can be different depending on the build type. In addition, apps hosted within Docker might have unusual shutdown behaviour.
CodePudding user response:
While you might see it as overkill in the beginning, I can recommend wrapping your console app in .NET Generic Host. This enables you to easily handle resource initialisation and cleanup, it also encapsulates logging and DI and nested services if available. The console app becomes easy to startup in an integration test, install as a Windows service (e.g. via Topshelf) or just keep running as a console app.
https://docs.microsoft.com/en-us/dotnet/core/extensions/generic-host
To get started you can run in command prompt
dotnet new worker
Then in Worker.cs you can override the StopAsync
public override async Task StopAsync(CancellationToken cancellationToken)
{
await Task.Delay(1000);
_logger.LogInformation("Ended!");
}
Running with dotnet run
you will see logging each second, and when you Ctrl C you will see "Ended!" after 1 second - here you do any resource cleanup needed.