如何在ASP.NET中侦听IIS关闭事件

时间:2022-03-17 05:54:13

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.

我在我的ASP.NET静态变量中,每次X插入都会将自身刷新到DB。问题是,如果我发布应用程序,IIS进程将被我的所有静态材料杀死。

How can I preserve it - or how can I flush it once ASP.NET application is shutting down?

如何保留它 - 或者如何在ASP.NET应用程序关闭后刷新它?

thank you

谢谢

4 个解决方案

#1


10  

Global.asax

Global.asax中

void Application_End(object sender, EventArgs e) 
    {
        //  SHUTDOWN CODE HERE
    }

#2


6  

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.

依赖应用程序关闭事件来保持数据库更新是有风险的。如果IIS重新启动,重新启动或停电,那么您将错过该事件。

#3


4  

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.

如前所述,强烈建议不要让应用程序在Application_End期间保留大数据,因为这可能在应用程序池关闭时触发,而不是在关闭开始时触发。这里有更详细的解释(但仍然很简短)。

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)

1)获取关闭时间限制 - IIS管理器 - >应用程序池 - > - >高级设置... - >过程模型组 - >关闭时间限制(秒)

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

2)在应用程序中创建一个线程/任务,运行时间是关闭时间限制的两倍,以确保可以捕获“关闭”状态。这个帖子应该

i) check if application pool is shutting down

i)检查应用程序池是否正在关闭

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

ii)如果关闭,请做你的东西。确保只执行一次

More correct way (as indicated here)

更正确的方法(如此处所示)

1) Create a class which implements IRegisteredObject

1)创建一个实现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)

2)注册你的对象(Global.asax.cs)

protected void Application_Start()
{
    // other initialization code here

    HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}

3) Unregistering (source)

3)取消注册(来源)

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.

首先调用Stop方法,并将immediate参数设置为false。该对象可以完成处理,调用UnregisterObject方法,然后返回,也可以在调用UnregisterObject方法之前立即返回并异步完成处理。

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.

如果在应用程序管理器的超时期限到期之前注册的对象未完成处理,则会立即将参数设置为true再次调用Stop方法。当immediate参数为true时,注册的对象必须在返回之前调用UnregisterObject方法;否则,应用程序管理员将删除其注册。


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):

作为旁注,我还将包含一些有关在ASP.NET Core 2.x中实现相同思想的细节。这可以使用IApplicationLifetime接口执行。示例(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.

注意:这仅在IIS(可能是其他Web服务器)中托管时才有效,但在IISExpress中不会触发IApplicationLifetime功能。

#4


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.

您可能不会收到IIS正在关闭的任何通知。想想如果IIS AppPool崩溃会发生什么,或者如果服务器失去电源将会发生什么。

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.

您不能依赖听到关机事件。如果IIS想要关闭,它不一定会通知您的应用程序。我建议你重新思考你的写缓冲/缓存场景 - 只保留你可以承受丢失的数据。

#1


10  

Global.asax

Global.asax中

void Application_End(object sender, EventArgs e) 
    {
        //  SHUTDOWN CODE HERE
    }

#2


6  

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.

依赖应用程序关闭事件来保持数据库更新是有风险的。如果IIS重新启动,重新启动或停电,那么您将错过该事件。

#3


4  

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.

如前所述,强烈建议不要让应用程序在Application_End期间保留大数据,因为这可能在应用程序池关闭时触发,而不是在关闭开始时触发。这里有更详细的解释(但仍然很简短)。

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)

1)获取关闭时间限制 - IIS管理器 - >应用程序池 - > - >高级设置... - >过程模型组 - >关闭时间限制(秒)

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

2)在应用程序中创建一个线程/任务,运行时间是关闭时间限制的两倍,以确保可以捕获“关闭”状态。这个帖子应该

i) check if application pool is shutting down

i)检查应用程序池是否正在关闭

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

ii)如果关闭,请做你的东西。确保只执行一次

More correct way (as indicated here)

更正确的方法(如此处所示)

1) Create a class which implements IRegisteredObject

1)创建一个实现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)

2)注册你的对象(Global.asax.cs)

protected void Application_Start()
{
    // other initialization code here

    HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}

3) Unregistering (source)

3)取消注册(来源)

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.

首先调用Stop方法,并将immediate参数设置为false。该对象可以完成处理,调用UnregisterObject方法,然后返回,也可以在调用UnregisterObject方法之前立即返回并异步完成处理。

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.

如果在应用程序管理器的超时期限到期之前注册的对象未完成处理,则会立即将参数设置为true再次调用Stop方法。当immediate参数为true时,注册的对象必须在返回之前调用UnregisterObject方法;否则,应用程序管理员将删除其注册。


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):

作为旁注,我还将包含一些有关在ASP.NET Core 2.x中实现相同思想的细节。这可以使用IApplicationLifetime接口执行。示例(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.

注意:这仅在IIS(可能是其他Web服务器)中托管时才有效,但在IISExpress中不会触发IApplicationLifetime功能。

#4


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.

您可能不会收到IIS正在关闭的任何通知。想想如果IIS AppPool崩溃会发生什么,或者如果服务器失去电源将会发生什么。

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.

您不能依赖听到关机事件。如果IIS想要关闭,它不一定会通知您的应用程序。我建议你重新思考你的写缓冲/缓存场景 - 只保留你可以承受丢失的数据。