How to listen to IIS shutdown event in ASP.NET
Asked Answered
S

5

18

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

Sociable answered 18/1, 2011 at 11:36 Comment(0)
S
18

Global.asax

void Application_End(object sender, EventArgs e) 
    {
        //  SHUTDOWN CODE HERE
    }
Sternson answered 18/1, 2011 at 11:39 Comment(2)
I don't have a Global.asax. I'm using .net7. If I need to create a Global.asax, where do I put it and what else goes in it? I do have a "Program.cs". Can I add code after "app.Run()"?Wasson
I think this answer is outdated.Wasson
O
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.

Ori answered 19/1, 2017 at 15:39 Comment(3)
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.Icebreaker
@vladimirkhozeyev - indeed the documentation 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.Ori
I think this answer is outdated. These days, people use 'Program.cs'. See below for my answer.Wasson
N
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.

Nervous answered 18/1, 2011 at 11:45 Comment(3)
yeah well, these cases I can't control. I want to control what I know and have...Sociable
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 assumptionsNervous
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).Macadamia
Q
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.

Quintain answered 18/1, 2011 at 11:48 Comment(0)
W
2

The modern way:

I'm using .Net7. I have a 'Program.cs' file which ends in the line:

app.Run();

I add a line of code after this (to call a static method on my Globals class):

app.Run();
Globals.GracefulShutdown();

To test it in Visual Studio, you obviously can't press the red stop button. Instead, go to your Windows system tray (via the caret symbol at the bottom of the screen, "Show hidden icons"), find the IIS Express icon and click it to shutdown or shutdown individual or all apps.

As others have said, you don't always have the luxury of a graceful shutdown and you don't want to do time-consuming stuff in the shutdown phase but it sounds like you're aware of those considerations.

Wasson answered 18/7, 2024 at 0:48 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.