Управление состоянием в ASP.NET
Страница 4. Серверные методы. 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). В этом случае у каждого отдельного сервера будет своя собственная коллекция, что в целом приведет к рассинхронизции.

 
« Предыдущая статья   Следующая статья »