如何检测在IIS7.5和Asp.Net 3.5+中当前的应用程序池是否正在关闭。

19

问题的主题已经很明确了 - 你有没有想法如何做到这一点?

我一直在查看System.Web.Hosting中的对象,但没有任何突出的东西。

原因是我正在遇到一两个应用程序错误,通常发生在重置时(它们大约间隔25小时,我已将应用程序池重置时间保留默认),因此我想知道它们是否发生在正在关闭的池中的线程上,还是正在启动的池中的线程。

4个回答

18

最近我偶然发现了这篇关于Brain.Save()的文章,从托管WCF的角度讲述了需要在Asp.Net中托管WCF服务时如何关闭所有已打开的侦听器,以便新的应用程序域中的WCF引擎能够再次打开它们。

正如文章所示,实现解决方案需要采用IRegisteredObject接口来创建对象实例,调用ApplicationManager.CreateObject方法,并使用HostingEnvironment.RegisterObject方法来注册对象(详见MSDN文档)。

当此对象的IRegisteredObject.Stop(bool)实现被传递false参数调用时,这意味着应用程序域正在关闭,并且该对象应被取消注册(类似全局释放),并调用HostingEnvironment.UnregisterObject方法。

如果被传递true参数调用,则表示您尚未及时取消注册,如果不立即取消注册,系统将自动为您完成。

当发生异常时,我肯定可以使用此机制来确定是否正在终止应用程序域。由于引发异常的对象的特性,如果它不是在关闭过程中,则必须在初始启动期间出现。

同样,我可能会开始将此持久化机制用于其他更复杂的静态信息!

历史

本文还解释了一些使用 IRegisteredObject 而不是在 global.asax 中实现 Application_StartApplication_End 方法的历史和原理:
传统 ASP.NET 应用程序可以通过在 global.asax 中实现 Application_Start 和 Application_Stop 等方法来挂钩应用程序生命周期事件(应用程序启动/关闭)。 然而,global.asax 用于应用程序代码。基础架构组件(其中包括 WCF 托管系统)需要一种机制来挂接 AppDomain 生命周期事件,而不涉及将基础架构代码倾泻到 global.asax 文件中。那个空间是为你,即用户保留的,我们用大量的托管 goo (指模块或处理器)来污染它,这是不礼貌的。相反,ASP.NET 在 Whidbey 发布期间做了一些很好的工作,打开了托管 API,并使像 WCF 这样的服务能够轻松地来挂接这些生命周期事件,以一种对应用程序代码不可见的方式。

1
服务器已经宕机了。该域名已经失效。 - EProgrammerNotFound
1
优秀的回答加一分!为了以后的参考,ASP.NET Core的工作方式有很大不同 -- 你需要实现一个机制来等待host.Run()方法完成,例如一个全局的CancellationToken,在主机终止后触发它。 - Lars Kemmann
@LarsKemmann - 非常好的观点 :)虽然这是一种完全不同的ASP.Net Core方法,但至少在某种程度上,它相当直观。 - Andras Zoltan

10

5
将实际代码添加到此处:
public class RecycleWatcher : IRegisteredObject
{
    public static bool IsRecycling { get; private set; }

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

然后,通过运行

启用它


new RecycleWatcher().Register();

之后只需检查IsRecycling属性,以了解您是否正在回收。

if (RecycleWatcher.IsRecycling) DoSomething();

谢谢,有一个改进:文档指出您必须在Stop方法中注销对象。 - dlxeon

2

如果您不确定在应用程序池回收时要执行的操作,但是如果将以下事件处理程序添加到Global.asax,则其中的代码将在关闭应用程序时运行。

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

1
谢谢,我已经记下来了。我想知道何时应该认真对待错误(并显示实际的错误页面),或者重新触发请求;听起来可能很疯狂,但如果我在引发错误后立即击中生成错误的url,它就不会再次发生!而且错误是静态保存数据导致的空引用异常 - 这告诉我它与应用程序启动/关闭有关。 - Andras Zoltan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接