I have in my ASP.NET static variable that flushes itself to DB every X insertions. Problem is, if I publish the application , the IIS process is killed with all my static material.
How can I preserve it - or how can I flush it once ASP.NET application is shutting down?
thank you
Global.asax
void Application_End(object sender, EventArgs e)
{
// SHUTDOWN CODE HERE
}
As already stated, it is highly not recommended to have application persist large data during Application_End
, as this might be triggered when application pool is shut down, not at the beginning of its shutting down. This is explained in more detailed (but still short) here.
If one still wants to catch the shutting down of an application pool for all cases that do not instantly kill it, can do the following:
Dirty way
1) Get shutdown time limit - IIS manager -> Application Pools -> -> Advanced settings ... -> Process model group -> Shutdown Time Limit (second)
2) Create an thread/task in the application to run twice as often as shutdown time limit to ensure that "shutting down" state can be caught. This thread should
i) check if application pool is shutting down
public bool IsShuttingDown()
{
return System.Web.Hosting.HostingEnvironment.ShutdownReason != ApplicationShutdownReason.None;
}
ii) if shutting down is on, do your stuff. Ensure that stuff is executed only once
More correct way (as indicated here)
1) Create a class which implements IRegisteredObject
public class HostingEnvironmentRegisteredObject : IRegisteredObject
{
// this is called both when shutting down starts and when it ends
public void Stop(bool immediate)
{
if (immediate)
return;
// shutting down code here
// there will about Shutting down time limit seconds to do the work
}
}
2) Register your object (Global.asax.cs
)
protected void Application_Start()
{
// other initialization code here
HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}
3) Unregistering (source)
The Stop method is first called with the immediate parameter set to false. The object can either complete processing, call the UnregisterObject method, and then return or it can return immediately and complete processing asynchronously before calling the UnregisterObject method.
If the registered object does not complete processing before the application manager's time-out period expires, the Stop method is called again with the immediate parameter set to true. When the immediate parameter is true, the registered object must call the UnregisterObject method before returning; otherwise, its registration will be removed by the application manager.
As a side note, I will also include some details about implementing the same think within ASP.NET Core 2.x. This can be performed using IApplicationLifetime interface. Example (Startup.cs):
public void Configure(IApplicationLifetime lifetime)
{
var quartz = new JobScheduler(Kernel);
lifetime.ApplicationStarted.Register(quartz.Start);
lifetime.ApplicationStopping.Register(quartz.Stop);
}
Note: this will work only when hosted within IIS (possible other Web servers), but not within IISExpress which will not trigger IApplicationLifetime
functionality.
Its kind of risky to rely on application shutdown events to keep a database updated. If IIS is force restarted, recycled or there is a power outage, then you are going to miss the event.
You might not receive any notification that IIS is shutting down. Think of what will happen if the IIS AppPool crashes or what will happen if the server simply loses power.
You cannot rely on ever hearing about shutdown events. If IIS wants to shut down, it's not necessarily going to notify your application. I recommend you re-think your writebuffering/caching scenario - only keep in memory the data that you can afford to lose.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With