web-dev-qa-db-fra.com

Les instances de classe statiques sont-elles uniques à une demande ou à un serveur dans ASP.NET?

Sur un site Web ASP.NET, les classes statiques sont-elles uniques à chaque demande Web ou sont-elles instanciées chaque fois que cela est nécessaire et GCed lorsque le GC décide de les supprimer?

Je pose la question parce que j’ai déjà écrit des classes statiques en C # et que le comportement est différent de celui que j’aurais prévu. Je me serais attendu à ce que les classes statiques soient uniques à chaque demande, mais cela ne semble pas être le cas.

S'ils ne sont pas uniques à chaque demande, existe-t-il un moyen de les autoriser?

PDATE:
La réponse que Driis m'a donnée était exactement ce dont j'avais besoin. J'utilisais déjà une classe singleton, mais elle utilisait une instance statique et était donc partagée entre des demandes, même si les utilisateurs étaient différents, ce qui dans ce cas était une mauvaise chose. En utilisant HttpContext.Current.Items résout mon problème parfaitement. Pour tous ceux qui trébuchent dans l’avenir sur cette question, voici ma mise en oeuvre, simplifiée et abrégée afin de faciliter la compréhension du schéma:

using System.Collections;
using System.Web;

public class GloballyAccessibleClass
{
    private GloballyAccessibleClass() { }

    public static GloballyAccessibleClass Instance
    {
        get
        {
            IDictionary items = HttpContext.Current.Items;
            if(!items.Contains("TheInstance"))
            {
                items["TheInstance"] = new GloballyAccessibleClass();
            }
            return items["TheInstance"] as GloballyAccessibleClass;
        }
    }
}
175
Dan Herbert

Vos classes statiques et vos champs d'instance statiques sont partagés entre toutes les demandes adressées à l'application et ont la même durée de vie que le domaine d'application. Par conséquent, vous devez faire attention lorsque vous utilisez des instances statiques, car vous pourriez avoir des problèmes de synchronisation et autres. Notez également que les instances statiques ne seront pas référencées par le GC avant le recyclage du pool d'applications et que, par conséquent, tout ce qui est référencé par l'instance statique ne le sera pas. Cela peut entraîner des problèmes d'utilisation de la mémoire.

Si vous avez besoin d'une instance ayant la même durée de vie qu'une requête, je suggérerais d'utiliser le HttpContext.Current.Items collection. C’est là, par conception, un lieu de stockage des éléments indispensables à la demande. Pour améliorer la conception et la lisibilité, vous pouvez utiliser le modèle Singleton pour vous aider à gérer ces éléments. Créez simplement une classe Singleton qui stocke son instance dans HttpContext.Current.Items. (Dans ma bibliothèque commune pour ASP.NET, j'ai une classe SingletonRequest générique à cette fin).

141
driis

Les membres statiques ont uniquement une étendue du processus de travail actuel, il n'a donc rien à voir avec les demandes, car différentes demandes peuvent être traitées ou non par le même processus de travail.

  • Afin de partager des données avec un utilisateur spécifique et entre plusieurs requêtes, utilisez HttpContext.Current.Session.
  • Afin de partager des données dans une requête spécifique, utilisez HttpContext.Current.Items.
  • Pour partager des données sur l’ensemble de l’application, écrivez un mécanisme à cet effet ou configurez IIS pour qu’il fonctionne avec un seul processus et écrivez une application singleton/use.

A propos, le nombre de processus de travail par défaut est 1, c'est pourquoi le Web regorge de personnes qui pensent que les membres statiques ont une portée de l'application entière.

27
Moshe Bixenshpaner

Étant donné que les types sont contenus dans un domaine d'application, je m'attendrais à ce que des classes statiques soient présentes tant que le domaine d'application n'est pas recyclé ou si la demande est servie par un autre domaine d'application.

Je peux penser à plusieurs façons de créer des objets spécifiques à une demande particulière en fonction de ce que vous voulez faire, par exemple. vous pouvez instancier l'objet dans Application.BeginRequest, puis le stocker dans un objet HttpRequest afin que tous les objets du pipeline de traitement de la demande puissent y accéder.

11
Sijin

S'ils ne sont pas uniques à chaque demande, existe-t-il un moyen de les autoriser?

Nan. Les membres statiques appartiennent au processus ASP.NET et sont partagés par tous les utilisateurs de l'application Web. Vous devrez vous tourner vers d'autres techniques de gestion de session telles que les variables de session.

4
rp.

Normalement, les méthodes, les propriétés et les classes statiques sont courantes au niveau Application. Tant que l'application vit, elles sont partagées.

Vous pouvez spécifier un comportement différent en utilisant l'attribut ThreadStatic. Dans ce cas, ils seront spécifiques au thread actuel, ce qui, je pense, est spécifique à chaque demande.
Je ne le conseillerais cependant pas car cela semble trop compliqué.

Vous pouvez utiliser HttpContext.Current.Items pour configurer le contenu d’une demande ou HttpContext.Current.Session pour configurer tout pour un utilisateur (sur plusieurs requêtes).

En général cependant, sauf si vous devez utiliser des choses comme Server.Transfer _, le meilleur moyen consiste à créer des objets une fois, puis à les transmettre explicitement via l'invocation de méthode.

0
Sklivvz