我正在尝试检测ASP.NET应用程序何时回收,原因是要修改web.config文件或手动回收IIS应用程序池。
最初我认为ASP.NET的Application_End方法可行,并尝试了以下内容:
protected void Application_End(object sender, EventArgs e)
{
File.AppendAllText("log.txt", DateTime.Now + "\n");
}
该文件是在第一次更改web.config文件时创建的,但后续更改未触发该事件。同样,在IIS中进行测试时,第一个手动应用程序池回收创建了该文件,但后来的文件没有 - 就像Application_End事件只触发一次一样。
每次池/应用程序回收时如何检测?
答案 0 :(得分:4)
以下可能有点像黑客,但你可以使用应用程序Cache
来解决它。每次加载页面时,您都可以检查特定键的缓存,如果该键不存在,则可以将其视为“循环”,然后添加密钥。不是最好的方法,但可能只适合您的需要。
EG。在您的基页Page_Load
或每个请求都会运行的某个位置,您可以执行以下操作:
if (HttpContext.Current.Cache["RecycleCheck"] != null)
{
// Add flag to cache
HttpContext.Current.Cache.Insert("RecycleCheck", "1", null,
DateTime.UtcNow.AddDays(2), // 2 days (most will recycle by then)
System.Web.Caching.Cache.NoSlidingExpiration);
// Do what you need because a recycle has happened
}
此方法不会在循环发生时将其取出。它只会在回收后的第一个请求中识别回收。
Application_Start
将是最可靠的地方,但它遇到了与黑客相同的问题,因为它发生在第一次请求回收之后。
答案 1 :(得分:2)
以下堆栈溢出问题提供了对此问题的良好答案:how to detect if the current application pool is winding up
要跟踪应用程序池回收,您需要实现IRegisteredObject接口,调用ApplicationManager.CreateObject来创建对象的实例,然后在应用程序启动时将其注册到HostingEnvironment.RegisterObject。
当使用false作为参数调用此对象的IRegisteredObject.Stop(bool)实现时,这是通知应用程序域正在关闭,并且该对象应该是未注册的(有点像全局配置)并且有一个调用到HostingEnvironment.UnregisterObject。
因此,使用此事件可以跟踪应用程序池何时被回收。
答案 2 :(得分:0)
你为什么不做这样的事情。调整计时器作业的频率,以提高确定appPool回收时间的准确性。
private readonly Timer timer = new Timer();
private DateTime start;
private string logFile;
void Application_Start(object sender, EventArgs e)
{
start= DateTime.Now;
logFile = Server.MapPath(
string.Concat("Log-",start.ToString("yyyyMMdd-HHmmss.fff"),".txt"));
timer.Interval = 1000;
timer.Elapsed += (s, ee)
=> File.WriteAllText(logFile,
string.Concat("App Start :", start, " Last Alive: ", DateTime.Now));
timer.Start();
}