Last active
February 27, 2021 17:52
-
-
Save ikalafat/33c1e41cd42a89263193cbf221292f93 to your computer and use it in GitHub Desktop.
Hangfire Shutdown Issues - example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Startup code in Program.cs: | |
private static async Task Main() | |
{ | |
#if DEBUG && !DEV | |
System.Threading.Thread.Sleep(10 * 1000); | |
#endif | |
log4net.Config.XmlConfigurator.Configure(); | |
Hierarchy h = (Hierarchy)log4net.LogManager.GetRepository(); | |
rootLogger = h.Root; | |
try | |
{ | |
rootLogger.Log(Level.Info, "XXXX Windows Service Host", null); | |
var kernel = await CreateKernel(); | |
rootLogger.Log(Level.Info, "XXXX Windows Service Host - Kernel created.", null); | |
bootstrapper.Initialize(() => kernel); | |
rootLogger.Log(Level.Info, "XXXX Windows Service Host - Bootstrapper initialized.", null); | |
try | |
{ | |
ServiceBase.Run(bootstrapper.Kernel.GetAll<ServiceBase>().ToArray()); | |
} | |
catch (Exception ex) | |
{ | |
rootLogger.Log(Level.Error, "Unhandled error.", ex); | |
throw; | |
} | |
finally | |
{ | |
bootstrapper.ShutDown(); | |
} | |
rootLogger.Log(Level.Info, "XXXX Windows Service Host - Stopped", null); | |
kernel.Dispose(); | |
} | |
catch (Exception ex) | |
{ | |
rootLogger.Log(Level.Error, "XXXX Windows Service Host - Service lifecyle", ex); | |
throw; | |
} | |
//Environment.Exit(0); | |
} | |
My service is bounded: | |
kernel.Bind<ServiceBase>().To<Service>(); | |
It inherits ServiceBase class. | |
OnStart code in Service.cs: | |
protected override void OnStart(string[] args) | |
{ | |
try | |
{ | |
foreach (var host in this.hosts) | |
{ | |
host.StartAsync(args).ContinueWith(t => | |
{ | |
if (t.IsCanceled) | |
{ | |
Logger.Info("Host start canceled, gracefully shutting down service."); | |
this.Stop(); | |
} | |
else if (t.IsFaulted) | |
{ | |
Logger.ErrorException("Fatal error. Shutting down service.", t.Exception); | |
this.Stop(); | |
} | |
}); | |
} | |
} | |
catch (System.Exception ex) | |
{ | |
Logger.ErrorException("Error in service startup.", ex); | |
throw; | |
} | |
} | |
"hosts" is array of sub-services which are called and started (usually one or two services in my case) that implement my IApplicationConsoleHost interface and they have StartAsync and StopAsync methods. | |
OnStop: | |
protected override void OnStop() | |
{ | |
try | |
{ | |
RequestAdditionalTime(30000); //Make sure that all tasks have finished | |
foreach (var host in this.hosts) | |
{ | |
host.StopAsync().Wait(); | |
} | |
} | |
catch (System.Exception ex) | |
{ | |
Logger.ErrorException("Error in service stop.", ex); | |
throw; | |
} | |
} | |
In my case, in my implementation of IApplicationConsoleHost, StartAsync contains SchedulerServer startup and job registration logic, while StopAsync shuts down the scheduler server. | |
Implementations of IApplicationConsoleHost are bound as singleton. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment