【发布时间】:2011-03-27 19:18:07
【问题描述】:
嗯 - 正如问题主题所述 - 关于如何做到这一点的任何想法?
我一直在查看 System.Web.Hosting 中的对象,但没有什么突出的。
原因?我收到一两个应用程序错误,这些错误通常发生在回收期间(它们相隔大约 25 小时发生,我将应用程序池回收时间设置为默认值),所以我想知道它们是否发生在正在关闭的池中的线程,或者正在启动(ed/ing)的线程。
【问题讨论】:
嗯 - 正如问题主题所述 - 关于如何做到这一点的任何想法?
我一直在查看 System.Web.Hosting 中的对象,但没有什么突出的。
原因?我收到一两个应用程序错误,这些错误通常发生在回收期间(它们相隔大约 25 小时发生,我将应用程序池回收时间设置为默认值),所以我想知道它们是否发生在正在关闭的池中的线程,或者正在启动(ed/ing)的线程。
【问题讨论】:
不确定当应用程序池回收时您想要做什么,但如果您将以下事件处理程序添加到 Global.asax,那么其中的代码将在应用程序关闭时运行。
protected void Application_End(object sender, EventArgs e)
{
}
【讨论】:
我最近偶然发现了this article on Brain.Save(),它从托管 WCF 的角度讨论了这个问题(他是 Steve Maine - Redmond 的 Connected Servies 部门的项目经理)。
当 WCF 服务托管在 Asp.Net 中时,他们需要能够执行此操作,因为他们需要能够关闭任何打开的侦听器,以便新应用程序域中的 WCF 引擎能够将它们全部打开再次。
正如文章所演示的,答案是实现IRegisteredObject interface,调用ApplicationManager.CreateObject 来创建您的对象的实例,然后将其注册到HostingEnvironment.RegisterObject(所有详细信息在该接口的MSDN 文档中)。
当使用false 作为参数调用此对象的IRegisteredObject.Stop(bool) 实现时,这是通知应用程序域正在关闭并且该对象应取消注册(有点像全局处置)并调用HostingEnvironment.UnregisterObject.
当它被调用true时,这意味着你没有及时取消注册,如果你不立即取消注册,它会为你完成。
我当然可以使用这种机制来查明,当异常发生时,AppDomain 是否被杀死。引发异常的相关对象的性质意味着,如果它不是在关闭时,它必须在初始启动期间。
不过,同样地,我很可能会开始研究这种持久性机制来获取我的其他一些更复杂的静态信息!
本文还解释了为什么要使用 IRegisteredObject 而不是 global.asax 中的 Application_Start 和 Application_End 方法的一些历史和理由:
传统的 ASP.NET 应用程序可以通过在 global.asax 中实现 Application_Start 和 Application_Stop 等方法来挂钩应用程序生命周期事件(应用程序启动/关闭)。但是,global.asax 用于应用程序代码。基础结构部分(WCF 托管系统就是其中之一)需要一种挂钩 AppDomain 生命周期事件的机制,该机制不涉及将基础结构代码转储到 global.asax 文件中。该空间是为您(用户)保留的,使用一堆托管粘性物来污染我们需要使整个事情正常工作的空间是不礼貌的。相反,ASP.NET 人员在 Whidbey 版本中做了一些出色的工作,开放了托管 API,让 WCF 之类的人更容易出现并以应用程序代码不可见的方式挂钩这些生命周期事件。
【讨论】:
host.Run() 方法完成,例如您在主机终止后触发的全局 CancellationToken。
您可以查看System.Web.Hosting.HostingEnvironment.ShutdownReason的值,当应用程序池不在关闭/回收过程中时,它将有ShutdownReason的None。
【讨论】:
添加实际代码来执行此操作:
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();
【讨论】: