2010-07-23 5 views
7

Je suis allé à la ronde avec ça depuis que j'ai commencé à programmer ASP 12 (ou plus) il y a des années et je n'ai jamais trouvé une solution géniale car l'architecture de ASP et ASP.NET a toujours été un marécage de mauvaises pratiques, des singletons magiques partagés, etc. Mon plus gros problème est avec l'objet HttpApplication avec ses événements sans événement (Application_Start, Application_End, etc.).Application_Start versus OnInit contre le constructeur

Si vous voulez faire des choses une fois pour toute la durée de vie d'une application HTTP, Application_Start est l'endroit idéal pour le faire. Droite? Pas exactement. Tout d'abord, ce n'est pas un événement en soi, c'est une convention de nommage magique qui, lorsqu'elle est suivie, provoque l'appel de la méthode une fois par AppDomain créé par IIS. Outre les conventions de nommage magiques étant une pratique horrible, j'ai commencé à penser qu'il pourrait y avoir une raison pour laquelle il n'existe pas d'événement Start sur l'objet HttpApplication. J'ai donc expérimenté avec des événements qui existent, tels que Init. Eh bien, ce n'est pas vraiment un événement non plus, c'est une méthode redoutable, qui est la meilleure chose suivante.

Il semble que la méthode Init() est appelée pour chaque instanciation d'un objet HttpApplication, ce qui se produit beaucoup plus d'une fois par AppDomain. Cela signifie que je pourrais tout aussi bien mettre ma logique de démarrage dans le constructeur de l'objet HttpApplication. Maintenant, ma question est, pourquoi ne pas mettre ma logique de démarrage dans le constructeur? Pourquoi existe-t-il encore Init() et dois-je m'occuper de Application_Start? Si oui, quelqu'un peut-il expliquer pourquoi il n'y a pas d'événement approprié ou de méthode substituable pour ce pseudo-événement dans l'objet HttpApplication? Et peut-on m'expliquer pourquoi dans une application ASP.NET typique, 8 instances de mes HttpApplication sont créées (ce qui fait que le constructeur et Init s'exécutent autant de fois, bien sûr, ce qui peut être atténué avec le verrouillage et un booléen statique partagé appelé initialized) lorsque mon application n'a qu'un seul AppDomain?

+0

doit probablement être fait en sorte que le cadre Application_Start pouvez configurer tous ces magiques des objets partagés. Peut-être que la classe est touchée avant cela et que le constructeur statique serait exécuté trop tôt. –

+0

@JoeKoberg, c'est un bon point. Vous avez moins de contrôle sur le moment où un constructeur statique est appelé qu'un appel de méthode explicite, bien sûr. Je ne vois toujours pas le besoin de 'Init()', cependant. Et 'Application_Start' et' Application_End' devraient toujours être des événements appropriés. –

Répondre

3

Appel Application_Start la première fois une instance de HttpApplication est créé, mais pas sur les instances suivantes semble un peu un hack. Peut-être que Microsoft n'a pas voulu expliquer le concept d'un constructeur statique à des gens qui ne voulaient pas vraiment savoir.

Application_End(), cependant, semble être une nécessité, car il n'y a pas C# équivalent d'un destructor/finaliseur statique. Comme les hacks vont, ce n'est pas si mal. Ça sent juste un peu drôle.

+0

Je suis d'accord Application_End() est nécessaire, mais pourquoi pas (et Application_Start) un événement approprié, vous pouvez écouter? Je comprends la compatibilité d'arrière-plan avec ASP classique, mais ne pas exposer l'événement n'a pas beaucoup de sens pour moi. –

0

Un objet HttpApplication est créé pour chaque requête simultanée. Chaque thread créé par ASP.NET obtient sa propre instance de HttpApplication. Les instances sont réutilisées pour les demandes suivantes de la même manière que les threads sont réutilisés à partir du pool de threads.

Utilisez la méthode Init pour initialiser les champs d'instance sur HttpApplication car ceux-ci ne seront initialisés que la première instance si elle est effectuée dans l'événement Application_Start. L'exécution Asp.Net conserve un pool d'objets HttpApplication.

+1

Mais pourquoi utiliseriez-vous la méthode Init() et non le constructeur? Qu'est-ce que la méthode Init() vous donne que le constructeur ne fait pas? –

4

Chaque requête .aspx est traitée par un seul objet qui est alloué à partir du pool (8 objets dans votre cas). La réponse à votre question, l'événement Application_Start est en effet appelée, mais seulement pour la première instance de HttpApplication, pas les suivantes, donc vous pouvez être sûr qu'elle est appelée exactement une fois au démarrage de votre application ou au pool d'applications de IIS est redémarré. Ainsi est l'événement Application_OnEnd (dernière instance)

pendant ce temps, les Init() et Dispose() sont appelés sur chaque instance de l'objet HttpApplication. Cela sera appelé sur chaque instance a.k.a. chaque demande. Pourquoi font-ils comme ça ..? peut-être pour équilibrer les performances et les optimisations de mémoire.

J'espère avoir répondu à votre question.

+0

Merci pour votre réponse. Cependant, vous n'avez pas mentionné le constructeur dans votre réponse. Pourquoi auriez-vous besoin de Init() quand vous pouvez faire la même chose dans le constructeur avec l'avantage supplémentaire de changer les champs privés en 'readonly'? Et pourquoi ne pas 'Application_Start' et les événements appropriés' Application_End' qui peut être accroché dans des gestionnaires d'événements appropriés? De plus, seront-ils appelés une fois par processus de travail, par domaine d'application ou quoi? –

+0

Une fois par processus de travail, non? Parce que vous pouvez créer des AppDomains dans votre propre processus de travail sans lancer Application_Start. Bien souvent, si vous ne créez pas vos propres domaines d'application, alors oui, cela devrait être par AppDomain ainsi que les processus de travail, afaik. – Henrik