Можно ли использовать свойство Application класса HttpApplication для вычисления текущих активных пользователей?
Я использую следующий код на странице Global.aspx веб-форм ASP.NET для подсчета количества текущих активных пользователей. Это работает, когда я провожу локальное тестирование.
Понимание заключается в том, что приложение является переменной уровня приложения и может быть доступно на уровне приложения. Таким образом, значение, сохраненное в одном сеансе, будет доступно в других сеансах.
<%@ Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
Application["TotalOnlineUsers"] = 0;
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
Application.Lock();
Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] + 1;
Application.UnLock();
}
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
Application.Lock();
Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] - 1;
Application.UnLock();
}
</script>
Но при переходе по этой ссылке https://docs.microsoft.com/en-us/dotnet/api/system.web.httpapplication?redirectedfrom=MSDN&amp;view=netframework-4.8 говорится, что переменные-члены могут использоваться для хранения данные запроса.
Основываясь на этом заявлении и приведенном ниже полном абзаце, может быть несколько экземпляров HttpApplication для одного приложения, если нет, приложение будет очень медленным, поскольку один экземпляр HttpApplication может обрабатывать только один запрос в один момент времени.
Из-за этого каждое HttpApplication будет иметь свою собственную переменную приложения, и счетчик будет сохранен на уровне HttpApplication.
Экземпляры класса HttpApplication создаются в инфраструктуре ASP.NET, а не непосредственно пользователем. Один экземпляр класса HttpApplication используется для обработки множества запросов за время своего существования. Однако он может обрабатывать только один запрос за раз. Таким образом, переменные-члены могут использоваться для хранения данных для каждого запроса.
Приложение генерирует события, которые могут обрабатываться пользовательскими модулями, реализующими интерфейс IHttpModule, или кодом обработчика событий, определенным в файле Global.asax. Пользовательские модули, реализующие интерфейс IHttpModule, можно поместить в папку App_Code или в DLL в папке Bin.
Итак, чтобы получить точное количество без каких-либо шансов просчета, должен ли я использовать статические переменные?
1 ответ
Я считаю, что ваш код будет работать правильно, если вы используете состояние сеанса InProc и не работаете в веб-ферме.
Как ни странно, слово «приложение» может иметь три разных значения:
- Ваше веб-приложение (то есть весь веб-сайт)
- Один из нескольких экземпляров HttpApplication , которые обслуживают запросы к вашему веб-приложению .
- Свойство HttpApplication.Application _
Когда в документации говорится, что свойство Application возвращает «текущее состояние приложения», имеется в виду ваше веб-приложение, а не отдельный экземпляр HttpApplication.
Это правда, что если вы добавите переменную-член в свой глобальный класс (который наследуется от HttpApplication), то переменная-член не будет совместно использоваться экземплярами HttpApplication. Но свойство Application является особенным: оно возвращает один и тот же объект HttpApplicationState независимо от того, какой экземпляр HttpApplication используется для доступа к свойству. Следовательно, любые значения, которые вы добавляете через свойство Application, будут общими для всех экземпляров HttpApplication. (И именно поэтому вы должны вызывать Lock и UnLock для синхронизации доступа; вам не нужно было бы делать это, если бы объект HttpApplicationState не был общим.)