17

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

Himberjack
  • 5,682
  • 18
  • 71
  • 115

4 Answers4

18

Global.asax

void Application_End(object sender, EventArgs e) 
    {
        //  SHUTDOWN CODE HERE
    }
Hawxby
  • 2,746
  • 21
  • 29
11

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.

Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
  • 2
    Thanks for your reference to IRegisteredObject! But I found that "immediate" flag means "true to indicate the registered object should unregister from the hosting environment". So I think it's better to make some checks and perform HostingEnvironment.UnregisterObject() before returning. – vladimir khozeyev Jun 17 '18 at 07:46
  • 1
    @vladimirkhozeyev - indeed [the documentation](https://msdn.microsoft.com/en-us/library/system.web.hosting.iregisteredobject.stop(v=vs.110).aspx) says that: "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". If I understand correctly, forgetting to unregister should not be an issue, since IIS should step in and unregister it anyway. – Alexei - check Codidact Jun 18 '18 at 13:48
5

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.

djeeg
  • 6,685
  • 3
  • 25
  • 28
  • 1
    yeah well, these cases I can't control. I want to control what I know and have... – Himberjack Jan 18 '11 at 11:47
  • 1
    if you don't care about missing these edge cases, then you may as not bother with the handling a graceful application shutdown. just make it part of your application assumptions – djeeg Jan 18 '11 at 11:51
  • The more "common edge case" is caring about a *graceful* shutdown, eg. to flush logging, without the unexpected ones.. app pools can be recycled fairly often (and for a large environment with many pools this means there could be many lost "common edge case" events). – user2864740 Jul 06 '17 at 20:56
3

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.

Sander
  • 25,685
  • 3
  • 53
  • 85