简体   繁体   English

IIS7.5 和 Asp.Net 3.5+ 如何检测当前应用程序池是否结束

[英]How to detect if the current application pool is winding up in IIS7.5 and Asp.Net 3.5+

Well - exactly as the question subject states - any ideas on how you might do this?好吧 - 正如问题主题所述 - 关于如何执行此操作的任何想法?

I've been looking over the objects in System.Web.Hosting but nothing is standing out.我一直在查看 System.Web.Hosting 中的对象,但没有什么特别突出的。

The reason?原因? I'm getting one or two application errors which are typically occuring during a recycle (they happen about 25 hours apart and I've left my app pool recycle time at the default) and so I want to know if they're happening on a thread that's in the pool that's shutting down, or the one that's start(ed/ing) up.我遇到一两个通常在回收期间发生的应用程序错误(它们大约相隔 25 小时发生,我将我的应用程序池回收时间保留为默认值),所以我想知道它们是否发生在正在关闭的池中的线程,或正在启动(ed/ing)的线程。

I recently stumbled across this article on Brain.Save() which talks about exactly this issue from the point of view of hosting WCF (he's Steve Maine - A program manager at Redmond on the Connected Servies Division).我最近偶然发现了这篇关于 Brain.Save()的文章,它从托管 WCF 的角度讨论了这个问题(他是 Steve Maine - Redmond Connected Servies Division 的项目经理)。

They need to be able to do this when a WCF service is hosted inside Asp.Net since they need to be able to shutdown any open listeners so that the WCF engine in the new app domain will be able to open them all up again.当 WCF 服务托管在 Asp.Net 中时,他们需要能够执行此操作,因为他们需要能够关闭任何打开的侦听器,以便新应用程序域中的 WCF 引擎能够再次打开它们。

As the article demonstrates, the answer is to implement the IRegisteredObject interface , call ApplicationManager.CreateObject to create an instance of your object and then register it with HostingEnvironment.RegisterObject (all detailed in the MSDN documentation for the interface).正如本文所演示的,答案是实现IRegisteredObject 接口,调用ApplicationManager.CreateObject来创建对象的实例,然后使用HostingEnvironment.RegisterObject注册它(所有详细信息都在接口的 MSDN 文档中)。

When this object's IRegisteredObject.Stop(bool) implementation is called with false as the parameter, this is notification that the app domain is being shut down and that the object should be unregistered (kind of like a global dispose) with a call to HostingEnvironment.UnregisterObject .当使用false作为参数调用此对象的IRegisteredObject.Stop(bool)实现时,这是通知应用程序域正在关闭并且应该通过调用HostingEnvironment.UnregisterObject

When it's called with true it means you've not unregistered in good time, and that if you don't Unregister immediately, it'll be done for you.当它以true调用时,这意味着您没有及时取消注册,如果您不立即取消注册,它将为您完成。

I can certainly use this mechanism to find out, when an exception occurs, if the AppDomain is being killed or not.当异常发生时,我当然可以使用这种机制来查明 AppDomain 是否被终止。 The nature of the object in question that throws the exception means that if it's not at shutdown, it must be during initial startup.抛出异常的相关对象的性质意味着如果它不在关闭时,它必须在初始启动期间。

Equally, however, I may well start looking at this persistence mechanism for some of my other more complicated static information!然而,同样地,我可能会开始为我的其他一些更复杂的静态信息研究这种持久性机制!

The History历史

The article also explains some of the history, and rationale, of why you would want to use IRegisteredObject rather than Application_Start and Application_End methods in global.asax :这篇文章还解释了一些历史和基本原理,说明为什么您想在global.asax中使用IRegisteredObject而不是Application_StartApplication_End方法:

Traditional ASP.NET applications can hook application lifecycle events (application startup/shutdown) by implementing methods like Application_Start and Application_Stop in global.asax.传统的 ASP.NET 应用程序可以通过在 global.asax 中实现 Application_Start 和 Application_Stop 等方法来挂钩应用程序生命周期事件(应用程序启动/关闭)。 However, global.asax is for application code.但是,global.asax 用于应用程序代码。 Infrastructure pieces (of which the WCF hosting system is one) need a mechanism of hooking AppDomain lifecycle events that do not involve dumping infrastructure code in your global.asax file.基础结构部分(WCF 托管系统是其中之一)需要一种挂钩 AppDomain 生命周期事件的机制,这些事件不涉及将基础结构代码转储到 global.asax 文件中。 That space is reserved for you, the user, and it would be rude of use to pollute that with a bunch of hosting goo we need to make the whole thing work.该空间是为您(用户)保留的,使用一堆托管粘性物质来污染它是不礼貌的,我们需要使整个事情正常进行。 Instead, the ASP.NET folks did some great work during the Whidbey release to open up the hosting API's and make it easy for people like WCF to come along and hook these lifecycle events in a way that's invisible to application code.相反,ASP.NET 人员在 Whidbey 发布期间做了一些伟大的工作,开放了托管 API,并使像 WCF 这样的人很容易出现并以对应用程序代码不可见的方式挂钩这些生命周期事件。

You can check the value of System.Web.Hosting.HostingEnvironment.ShutdownReason , when the app pool is not in the process of closing / recycling it will have the ShutdownReason of None.您可以检查System.Web.Hosting.HostingEnvironment.ShutdownReason的值,当应用程序池不在关闭/回收过程中时,它的ShutdownReason将为 None。

Adding the actual code to do this:添加实际代码来执行此操作:

public class RecycleWatcher : IRegisteredObject
{
    public static bool IsRecycling { get; private set; }

    public void Register()
    {
        HostingEnvironment.RegisterObject(this);
    }
    public void Stop(bool immediate)
    {
        IsRecycling = true;
    }
}

Then enable it by running然后通过运行启用它

new RecycleWatcher().Register();

After that just check that property for IsRecycling to know if you are recyling or not.之后,只需检查 IsRecycling 的属性即可了解您是否正在回收。

if (RecycleWatcher.IsRecycling) DoSomething();

Not sure exactly what you want to do when the appication pool recycles but if you add the below event handler to Global.asax then the code in it will run when the application is shut down.不确定当应用程序池回收时你到底想做什么,但如果你将下面的事件处理程序添加到 Global.asax 那么其中的代码将在应用程序关闭时运行。

 protected void Application_End(object sender, EventArgs e)
 {
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM