Можно ли поймать событие повторного использования в global.asax?
Я знаю, что Application_End будет запущен, но есть ли способ узнать, что это было вызвано повторным запуском пула приложений?
спасибо, Ливен Кардоен aka Johlero


Я никогда не пробовал этого сам, но вы можете попробовать прикрепить обработчик событий к событию ProcessExit в AppDomain.
...
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnExit);
...
void OnExit(object sender, EventArgs e) {
// do something
}
Надеюсь, это поможет!
Это задержит большинство структурированных разборок процессов, например - но я не уверен, что он уловит все слезы. например blogs.msdn.com/jmstall/archive/2006/11/26/… Перезагрузка процесса убьет процесс, если он кажется зависшим - ваш обработчик не будет вызван.
Итак, вот идея, как это могло бы работать.
На основе моего предыдущий ответ (прикрепить к AppDomain.CurrentDomain.ProcessExit) и комментария Стефбу:
This will trap most structured process teardowns e.g. - but I'm not sure that it will trap all tear downs. e.g. http://blogs.msdn.com/jmstall/archive/2006/11/26/process-exit-event.aspx Process recycle will kill the process if it seems to be hung - your handler wouldn't get called.
Предлагаю следующую стратегию:
В (обычном) обработчике ProcessExit (который, как мы предполагаем, не будет вызываться при перезапуске пула приложений) запишите какой-нибудь файл на диск, например «app_domain_end_ok.tmp».
Затем в Application_Start вашего global.asax проверьте этот файл. Если он не существует, это признак того, что приложение не было завершено должным образом (или что это был первый раз, когда оно запускалось). Не забудьте удалить этот файл с диска после проверки.
Сам я не пробовал, но попробовать стоит.
Я не проверял это, но подозреваю, что у ресайклера процесса есть две стратегии: 1) сигнал завершения процесса и ожидание во время опроса для выхода из процесса - он должен запускать ProcessExit в нормальных условиях. 2) По таймауту ожидания убить PID.
Я нашел эту статью на Блог Скотта Гатриза:
Ведение журнала событий завершения работы приложения ASP.NET
Someone on a listserv recently asked whether there was a way to figure out why and when ASP.NET restarts application domains. Specifically, he was looking for the exact cause of what was triggering them on his application in a production shared hosted environment (was it a web.config file change, a global.asax change, an app_code directory change, a directory delete change, max-num-compilations reached quota, \bin directory change, etc).
Thomas on my team has a cool code-snippet that he wrote that uses some nifty private reflection tricks to capture and log this information. It is pretty easy to re-use and add into any application, and can be used to log the information anywhere you want (the below code use the NT Event Log to save it – but you could just as easily send it to a database or via an email to an admin). The code works with both ASP.NET V1.1 and ASP.NET V2.0.
Simply add the System.Reflection and System.Diagnostics namespaces to your Global.asax class/file, and then add the Application_End event with this code:
public void Application_End() {
HttpRuntime runtime =
(HttpRuntime) typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime",
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField,
null, null, null);
if (runtime == null)
return;
string shutDownMessage =
(string) runtime.GetType().InvokeMember("_shutDownMessage",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
null, runtime, null);
string shutDownStack =
(string) runtime.GetType().InvokeMember("_shutDownStack",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
null, runtime, null);
if (!EventLog.SourceExists(".NET Runtime")) {
EventLog.CreateEventSource(".NET Runtime", "Application");
}
EventLog log = new EventLog();
log.Source = ".NET Runtime";
log.WriteEntry(String.Format(
"\r\n\r\n_shutDownMessage = {0}\r\n\r\n_shutDownStack = {1}",
shutDownMessage, shutDownStack),
EventLogEntryType.Error);
}
Мне гораздо больше удалось подключиться к событию DomainUnload, оно запускается при перезапуске AppPool и остановке самого AppPool.
AppDomain.CurrentDomain.DomainUnload += this.CurrentDomainOnProcessExit;
Повторное использование приложений может быть довольно жестким делом в зависимости от состояния вашего процесса - наихудший сценарий - это вызов Win32 :: TerminateProcess. Невозможно уловить такой результат в вашем процессе. Чего вы пытаетесь достичь? Промывка какое-то состояние?