État de l'application
Vous pouvez partager des informations dans votre application en utilisant la classe HttpApplicationState, plus généralement accessible par l'intermédiaire de la propriété Application de l'objet HttpContext. Cette classe expose un dictionnaire d'objets de type clé-valeur que vous pouvez utiliser pour stocker les objets .NET Framework et les valeurs scalaires relatives aux nombreuses demandes Web émanant de plusieurs clients.
Cette rubrique donne une vue d'ensemble de l'état de l'application, en aborde l'utilisation, présente les collections d'état de l'application et couvre aussi la synchronisation de l'état de l'application.
Vue d'ensemble de l'état de l'application
Une application ASP.NET est la somme de l'ensemble des fichiers, pages, gestionnaires, modules et du code qui résident dans un répertoire virtuel donné et ses sous-répertoires, que les utilisateurs peuvent demander par l'intermédiaire d'une hiérarchie de répertoires virtuelle.
Par exemple, si vous développez une application qui calcule les bénéfices de l'investissement fait pour l'intranet de votre société, vous pouvez la publier dans un répertoire virtuel nommé \Invest sur un serveur Web. La structure de répertoire pour une telle application peut avoir l'apparence suivante :
\Invest
\bin
\image
\xml
Une instance de la classe HttpApplicationState est créée la première fois qu'un client demande une ressource URL à partir de l'espace de noms du répertoire virtuel d'une application ASP.NET particulière. C'est le cas pour chaque application Web stockée sur l'ordinateur. L'accès à cette instance de chaque application est possible grâce à une propriété HttpContext nommée Application. Tous les modules HttpModule et gestionnaires HttpHandler, comme une page ASP.NET, ont accès à une instance du contexte et donc à la propriété Application pendant une demande Web donnée.
ASP.NET fournit la prise en charge de l'état de l'application suivante :
- Fonctionnalité d'état facile à utiliser, compatible avec les versions antérieures d'ASP, fonctionnant avec tous les langages pris en charge par .NET et cohérente par rapport aux autres API .NET Framework.
- Dictionnaire d'état de l'application à disposition de tous les gestionnaires de demande appelés dans une application. Contrairement aux services IIS (Internet Information Services) et aux versions antérieures d'ASP, où seules les pages peuvent accéder à l'état de l'application, toutes les instances IHttpHandler et IHttpModule peuvent stocker des variables globales dans le dictionnaire et les en extraire.
- Mécanisme de synchronisation simple et intuitif qui permet aux développeurs de facilement coordonner un accès simultané aux variables stockées dans l'état de l'application.
- Valeurs de l'état de l'application accessibles uniquement à partir du code s'exécutant dans le contexte de l'application d'origine. Les autres applications s'exécutant sur le système ne peuvent pas accéder aux valeurs ni les modifier.
Le moyen le plus courant d'accéder à l'état de l'application est la propriété Application de l'objet Page.
Utilisation de l'état de l'application
En fait, les variables de l'état de l'application sont des variables globales pour une application ASP.NET donnée. Comme les développeurs d'applications côté client, les programmateurs ASP.NET doivent systématiquement considérer l'impact du stockage comme une variable globale.
Les points suivants sont particulièrement importants dans ce contexte :
- Impact sur la mémoire du stockage dans l'état de l'application. La mémoire occupée par les variables stockées dans l'état de l'application n'est pas libérée tant que la valeur n'est pas supprimée ou remplacée, contrairement à une page Web individuelle où toutes les ressources sont détruites à la conclusion d'une demande Web. La conservation permanente de jeux d'enregistrements de 10 Mo rarement utilisés dans l'état de l'application n'est pas, par exemple, la meilleure utilisation des ressources système. Pour cet exemple extrême, vous pouvez trouver de meilleures solutions à l'aide du Cache ASP.NET.
- Implications d'accès concurrentiel et de synchronisation du stockage et de l'accès à une variable globale dans un environnement serveur multithread. Plusieurs threads d'une application peuvent accéder en même temps aux valeurs stockées dans l'état de l'application. Vous devez toujours faire particulièrement attention à ce qu'un objet à portée d'application contienne une prise en charge intégrée de la synchronisation s'il est libre de threads. Tous les objets personnalisés qui ciblent le Common Language Runtime sont libres de threads. Si un objet à portée d'application n'est pas libre de threads, vous devez vous assurer que les méthodes de synchronisation explicites sont codées autour de lui pour éviter les conflits, les conditions de course et les violations d'accès.
- Implications d'évolutivité du stockage et de l'accès à une variable globale dans un environnement serveur multithread. Il faut utiliser des verrous à chaque tentative d'écriture ou de mise à jour dans un fichier. Les verrous qui protègent des ressources globales sont eux-mêmes globaux et le code s'exécutant sur plusieurs threads qui accèdent à des ressources globales finit par être confronté à ces verrous. Ceci conduit le système d'exploitation à bloquer les threads de travail jusqu'à ce que le verrou soit disponible. Dans les environnements serveur à forte charge, ce blocage peut provoquer une grave surcharge de threads sur le système. Sur les systèmes multiprocesseurs, cela peut conduire à une sous-utilisation des processeurs (puisque pour un processeur tous les threads peuvent théoriquement être au point mort en attendant un verrou partagé) et à des baisses considérables de l'évolutivité globale.
- Implications de cycle de vie des informations stockées dans l'état de l'application. Le domaine d'application .NET Framework ou le processus hébergeant une application .NET peuvent être détruits à tout moment pendant l'exécution de l'application (résultant de pannes, mises à jour du code, redémarrages programmés du processus, etc.). Étant donné que les données stockées dans l'état de l'application ne sont pas durables, elles sont perdues si l'hôte qui les contient est détruit. Si vous souhaitez que l'état survive à ces types de défaillances, vous devez le stocker dans une base de données ou un autre magasin durable.
- L'état de l'application n'est pas partagé par une batterie de serveurs Web (où une application est hébergée par plusieurs serveurs) ni par un jardin Web (où une application est hébergée par plusieurs processus sur le même serveur). Les variables stockées dans l'état de l'application dans l'un de ces scénarios sont globales uniquement par rapport au processus particulier dans lequel l'application est en cours d'exécution. Chaque processus d'application peut avoir différentes valeurs. Par conséquent, vous ne pouvez pas compter sur l'état de l'application pour stocker des valeurs uniques ou mettre à jour des compteurs globaux, par exemple, dans les scénarios de batterie de serveurs Web ou de jardin Web.
En dépit de ces points, des variables au niveau de l'application bien conçues peuvent être très puissantes dans les applications Web. Vous pouvez procéder à un chargement et un calcul uniques (ou peu fréquents) des informations puis utiliser l'état de l'application pour les mettre en cache pour un accès en mémoire rapide lors des demandes Web ultérieures.
Un site Web boursier, par exemple, peut saisir des informations financières détaillées (peut-être 40 Mo de données) toutes les 5 minutes pendant la journée à partir d'une base de données puis les mettre en cache dans l'état de l'application où les demandes de recherche ultérieures pourront y accéder. Il en résulte une amélioration considérable de la performance par demande, puisque les demandes entrantes ne nécessitent pas d'allers-retours interprocessus, inter-ordinateurs ou vers une base de données. D'autre part, pour les gros blocs de données transitoires, l'utilisation du cache peut être une solution pour mieux employer les ressources.
Collections de l'état de l'application
La classe HttpApplicationState expose deux collections d'état : Contents et StaticObjects
La collection Contents expose tous les éléments de variable ajoutés à la collection d'état de l'application directement par l'intermédiaire du code. Par exemple :
' Visual Basic code from within a page, a handler, or Global.asax.
Application("Message") = "MyMsg"
Application("AppStartTime") = Now
[C#]
// C# code from within a page, a handler, or Global.asax.
Application["Message"] = " MyMsg";
Application["AppStartTime"] = DateTime.Now;
Pour des raisons de compatibilité avec les versions antérieures de ASP, ces variables sont aussi accessibles à l'aide de la propriété Contents de l'objet de l'application, comme dans l'exemple suivant.
' Visual Basic code from within a page, a handler, or Global.asax.
Application.Contents("Message") = " MyMsg"
Application.Contents("AppStartTime") = Now
[C#]
// Visual Basic code from within a page, a handler, or Global.asax.
Application.Contents["Message"] = " MyMsg";
Application.Contents["AppStartTime"] = DateTime.Now;
La collection StaticObjects expose tous les éléments de variable ajoutés à la collection de l'état de l'application par l'intermédiaire des balises <
object runat="server">
dans le fichier Global.asax avec une portée d'application. Par exemple :
' Global.asax definition.
<object runat="server" scope="application" ID="MyInfo" PROGID="MSWC.MYINFO">
</OBJECT>
Les objets ne peuvent pas être ajoutés à la collection StaticObjects à partir de n'importe quel emplacement d'une application ASP.NET. La collection lève NotSupportedException si vous tentez d'ajouter des objets directement par l'intermédiaire du code.
Notez que le compilateur de pages .NET injecte automatiquement des références à des membres dans tous les objets stockés dans la collection StaticObjects au moment de la compilation de la page, de manière à ce que les développeurs puissent accéder à ces objets d'application au moment de la demande de la page sans avoir à référencer la collection Application. Par exemple :
<html>
</body>
Application Level Title: <%= MyInfo.Title %>
<body>
</html>
Synchronisation de l'état de l'application
Plusieurs threads dans une application peuvent accéder en même temps aux valeurs stockées dans l'état de l'application. Par conséquent, lorsque vous créez quelque chose qui a besoin d'accéder aux valeurs de l'état de l'application, vous devez toujours veiller à ce que l'objet de l'état de l'application soit libre de threads et effectue sa propre synchronisation interne ou procède aux étapes de synchronisation manuelles pour se protéger des conditions de course, conflits et violations d'accès.
La classe HttpApplicationState fournit deux méthodes, Lock et Unlock, qui ne permettent qu'à un seul thread d'accéder aux variables de l'état de l'application.
L'appel de Lock sur l'objet Application conduit ASP.NET à bloquer les tentatives d'accès du code s'exécutant sur d'autres threads de travail à l'état de l'application. Ces threads sont débloqués uniquement lorsque le thread qui a appelé Lock appelle la méthode Unlock correspondante sur l'objet Application.
L'exemple de code suivant illustre l'utilisation du verrouillage pour se protéger contre les conditions de course.
' Visual Basic code from within a page, a handler, or Global.asax.
Application.Lock()
Application("SomeGlobalCounter") = _
CType(Application("SomeGlobalCounter"), Integer) + 1
Application.UnLock()
[C#]
// C# code from within a page, a handler, or Global.asax.
Application.Lock();
Application["SomeGlobalCounter"] =
(int)Application["SomeGlobalCounter"] + 1;
Application.UnLock();
Si vous n'appelez pas explicitement Unlock, le .NET Framework supprime automatiquement le verrou une fois la demande terminée, le délai de la demande dépassé ou en cas d'erreur non gérée pendant l'exécution de la demande, et provoque l'échec de la demande. Ce déverrouillage automatique évite les blocages de l'application.