Управление состоянием в ASP.NET - Серверные методы. Application
ОГЛАВЛЕНИЕ
Серверные методы
Application
Контейнер Application является глобальным и доступным из всех страниц, http модулей и http хэндлеров веб-приложения. Он должен использоваться для сохранения информации общей для всего приложения. Как и все вышеуказанные контейнеры, Application является коллекцией типа ключ-значение. Поскольку этот контейнер был доступен еще в предыдущих версиях ASP, то для совместимости Application разделен на две коллекции Contents и StaticObjects. Коллекция Contents является динамической, т.е. добавлять в нее и удалять из нее значения можно в процессе работы приложения (runtime). Доступ к ней производится либо через индексатор Application, либо через свойство Contents. Следующий пример демонстрирует ее использование:
// два эквивалентных способа доступа
// через индексатор Application
Application["Message"] = "My string";
Application["AppStartTime"] = DateTime.Now;
string s = (string)Application["Message"];
DateTime startTime = (DateTime)Application["AppStartTime"];
// через свойство Contents
Application.Contents["Message"] = "My string";
Application.Contents["AppStartTime"] = DateTime.Now;
string s = (string)Application.Contents["Message"];
DateTime startTime = (DateTime)Application.Contents["AppStartTime"];
Коллекция StaticObjects является read-only коллекцией, т.е. добавление и удаление элементов в нее в runtime запрещено. Элементы в этой коллекции определяются в файле Global.asax с помощью тега <object runat="server" scope="application">. Например:
<object runat="server" scope="application" id="AppStr" class="System.Text.StringBuilder"/>
Таким образом, в коллекцию добавлен новый объект типа StringBuilder с ключом AppStr.
Использовать его можно либо непосредственно из aspx файла:
<form id="Form1" method="post" runat="server">
AppStr value: <%= AppStr %>
</form>
либо из кода на C# или на другом языке программирования:
StringBuilder sb = (StringBuilder)Application.StaticObjects["AppStr"];
sb.Append("My String");
Label1.Text = Application.StaticObjects["AppStr"].ToString();
Отметим еще раз, что этот способ введен исключительно для совместимости с предыдущими версиями ASP и использовать его в данный момент не рекомендуется.
Поскольку значения контейнера Application доступны из всех страниц, то в случае одновременного обращения нескольких потоков к одному значению возникает проблема синхронизации. В качестве решения используются два метода: Lock() и Unlock(). Вызов метода Lock заставляет ASP.NET блокировать все попытки доступа любых других потоков к любой информации из Application. Блокировка снимается вызовом метода Unlock из потока инициировавшего блокировку. Следующий пример демонстрирует их использование:
Application.Lock();
Application["SomeGlobalCounter"] = (int)Application["SomeGlobalCounter"] + 1;
Application.UnLock();
Во избежание ситуации deadlock блокировка автоматически снимается в таких случаях: после успешного выполнения запроса, после ошибки тайм-аута соединения либо после любого неперехваченного исключения, возникшего в процессе обработки запроса пользователя.
Одним из недостатков Application является неограниченное время жизни его объектов. Т.е. значения, записанные в эту коллекцию, будут в ней существовать до тех пор, пока они не будут явно удалены (методы Remove, RemoveAll, RemoveAt, присвоение null).
/ удаление SomeGlobalCounter из Application методом Remove
Application.Remove("SomeGlobalCounter");
// удаление SomeGlobalCounter из Application присвоением null
Application["SomeGlobalCounter"] = null;
В противном случае они будут существовать до завершения работы приложения либо перезагрузки веб-сервера. С другой стороны, при перезапуске веб-сервера уничтожаться все значения Application, что может усложнить жизнь администратора сервера.
Также Application неприменим при развертывании приложения на нескольких физических серверах (web farm). В этом случае у каждого отдельного сервера будет своя собственная коллекция, что в целом приведет к рассинхронизции.