Как уже говорилось, настоятельно не рекомендуется, чтобы приложение сохраняло большие данные во время Application_End
, так как это может быть вызвано, когда пул приложений выключен, а не в начале его выключения.Это объясняется более подробно (но все еще кратко) здесь .
Если кто-то все еще хочет поймать завершение работы пула приложений для всех случаев, которые не уничтожают его немедленно, можно выполнитьследующее:
Грязный путь
1) Получить ограничение по времени выключения - диспетчер IIS -> Пулы приложений -> -> Расширенные настройки ... -> Группа моделей процесса-> Ограничение времени выключения (секунда)
2) Создайте поток / задачу в приложении, чтобы запускать его вдвое чаще, чем ограничение времени выключения, чтобы обеспечить возможность захвата состояния «выключения».Этот поток должен
i) проверить, закрывается ли пул приложений
public bool IsShuttingDown()
{
return System.Web.Hosting.HostingEnvironment.ShutdownReason != ApplicationShutdownReason.None;
}
ii) если выключение включено, сделайте свое дело.Убедитесь, что материал выполняется только один раз
Более правильный путь (как указано здесь )
1) Создайте класс, который реализует IRegisteredObject
public class HostingEnvironmentRegisteredObject : IRegisteredObject
{
// this is called both when shutting down starts and when it ends
public void Stop(bool immediate)
{
if (immediate)
return;
// shutting down code here
// there will about Shutting down time limit seconds to do the work
}
}
2) Зарегистрировать ваш объект (Global.asax.cs
)
protected void Application_Start()
{
// other initialization code here
HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}
3) Отменить регистрацию ( источник )
СтопМетод сначала вызывается с непосредственным параметром, установленным в false.Объект может либо завершить обработку, вызвать метод UnregisterObject и затем вернуться, либо он может сразу же вернуться и завершить обработку асинхронно перед вызовом метода UnregisterObject.
Если зарегистрированный объект не завершает обработку до времени менеджера приложений,истекает период истечения, метод Stop вызывается снова с непосредственным параметром, установленным в true.Если непосредственный параметр имеет значение true, зарегистрированный объект должен вызвать метод UnregisterObject перед возвратом; в противном случае его регистрация будет удалена диспетчером приложений.
Какпримечание, я также включу некоторые подробности о реализации той же идеи в ASP.NET Core 2.x.Это может быть выполнено с использованием интерфейса IApplicationLifetime .Пример (Startup.cs):
public void Configure(IApplicationLifetime lifetime)
{
var quartz = new JobScheduler(Kernel);
lifetime.ApplicationStarted.Register(quartz.Start);
lifetime.ApplicationStopping.Register(quartz.Stop);
}
Примечание. Это будет работать только в том случае, если оно размещено в IIS (возможно, на других веб-серверах), но не в IISExpress, который не будет запускать функциональность IApplicationLifetime
.