8
votes

Pourquoi mon «contexte» de la fonction statique de l'ASP.NET est la crossover entre les sessions utilisateur?

Je pense avoir besoin d'aide aider à comprendre comment les objets statiques persistent dans une application ASP.NET. J'ai ce scénario:

quelquefile.cs dans une bibliothèque de classe: p> xxx pré>

quelque therphone.cs dans une bibliothèque de classe: p>

01/01/01.000 abababababab  (session #1, first call)
01/01/05.000 cdcdcdcdcdcd  (session #2, first call - started 5 seconds after session #1)
01/01/21.000 cdcdcdcdcdcd  (session #1 returns after the wait but has assumed the function context from session #2!!!!!)
01/01/25.000 cdcdcdcdcdcd  (session #2 returns with its own context)


1 commentaires

Merci à tous pour l'aide. Règles Stackoverflow. :)


5 Réponses :


12
votes

Chaque demande à un site ASP.NET est entrée et est traitée sur son propre thread. Mais chacun de ces threads appartient à la même application. Cela signifie que tout ce que vous marquez comme statique est partagé dans toutes les demandes, et donc aussi toutes les sessions et utilisateurs.

Dans ce cas, la fonction MYFUNCUNC La partie de votre classe de page est copiée sur le dessus du membre STATIC FUNC dans A avec chaque Page_init, et donc chaque fois que tout utilisateur effectue une page_init, il est remplaçant le a.func utilisé par toutes les demandes .


5 commentaires

Je comprends que l'adresse de fonction est remplacée. Je ne comprends cependant pas pourquoi les données accédées dans la fonction se croisent également. Pourquoi la session n ° 1, qui a une session.sessidid = abababababababab, alors que vous appelez à nouveau myfunc, a soudainement session.sessionid = CDCDCDCDCDCD?


Parce que le délégué capture l'ensemble de cette méthode, y compris l'objet de session en cours lorsque vous l'avez attribués au délégué statique.


Parce qu'avant la session n ° 1 appelle la méthode statique A.func () dans la session de session de constructeur Q () N ° 2 a remplacé cette fonction avec sa propre implémentation. Vous appelez une fonction complètement différente de la 2e fois.


Cela fait cela au moyen d'une fermeture.


+1 Une fois que Jeff a mentionné une fermeture, la lumière a cliqué pour moi. Merci pour votre réponse et vos commentaires.



4
votes

Les données statiques sont partagées parmi l'ensemble de l'ensemble domaine d'application de votre webApp. En bref, il est partagé parmi tous les threads servant des demandes de votre webApp, ce n'est pas lié à une session / thread / utilisateur, mais à la webApp dans son ensemble. (Contrairement à PHP, où chaque demande vit dans sa propre barre d'environnement isolé Quelques boutons fournis - tels que la variable de session.)


1 commentaires

Comme si j'essaie de verbaliser correctement dans mon commentaire à Joel, je comprends pourquoi la référence de fonction est partagée entre le domaine de l'application. Je ne comprends pas pourquoi les variables qui sont session / threads / utilisateur liées dans la logique de la fonction sont également partagées entre le domaine de l'application.



2
votes

Une solution que vous pourriez envisager est d'utiliser [Threadstatic].

http://msdn.microsoft. com / fr-nous / bibliothèque / system.threadsticattribute (vs.71) .aspx

Il fera votre statistique par fil. Il y a cependant des cavales, cependant, vous devriez tester.


9 commentaires

Outre la note MSDN dans votre lien sur les valeurs initiales, quelles sont les mises en garde?


Cela ne fonctionnera pas dans ASP.NET. Vous ne pouvez pas prédire quel fil fera service une demande donnée.


@Brannon - mais ne sommes-nous pas garantis qu'un seul thread de service une seule demande? Je pense que c'est mon problème - que Myfunc d'un thread a été modifié au milieu de l'opération par une autre tâche de Myfunc d'un autre fil.


Une alternative aux variables threadstatiques est httpcontext.current.items qui est scopé à une demande distincte (voir Hanselman. com / blog / ... par exemple).


@Matt - En général, un seul thread conservera la demande. Le problème avec ThreadStatic est que les valeurs persisteront sur ce fil après la fin de la requête. Bien que cela puisse fonctionner dans votre scénario, ce n'est pas ce que vous voulez. Utilisez httpcontext.items.


@Nissan +1 - Les tests jusqu'à présent avec ThreadStatic semble résoudre mon problème. Je suis préoccupé par les mises en garde et ce que Brannon soulevé, d'autant plus que la version de production de ce code aura potentiellement des dizaines d'utilisateurs simultanés.


@Brannon +1 - Je pense que cela reste bien dans mon scénario. Tant que le même service de fil de la même demande, je crois que je suis en sécurité. La première chose qui se produit sur chaque demande est une réaffectation de cette variable statique, ce qui lui donne la "portée" de la nouvelle demande.


Rappelez-vous simplement: le même utilisateur finira probablement sur de nombreux threads différents au cours d'une session.


@Matt - Vous devriez vraiment regarder à l'aide de httpcontext.items, il est / conçu / pour ce scénario exact!



4
votes

Je n'essaierai pas d'améliorer les autres réponses des membres statiques, mais souhaitez-vous signaler une autre façon de coder votre problème immédiat.

En tant que solution, vous pouvez faire une version axée sur l'instance. de votre classe A , stockez-la dans une variable de niveau de page et transmettez-la sur q S de la page charge: xxx

En fait, s'il n'y a pas besoin de dépendre de A2 plus tôt, vous pouvez simplement l'instancier lorsque vous créez votre instance de q dans page_load < / code>.

EDIT: Pour répondre à la question que vous avez soulevée dans d'autres commentaires, la raison des variables sont partagées est que les demandes partagent le même délégué, qui n'a que une copie unique de ses variables. Voir Jon Skeet's's La beauté des fermetures pour plus de détails. >


1 commentaires

Doh !!!!!!! Cela me fait du sens pour moi maintenant. Je ne me suis même pas réalisé que j'avais mis en place une fermeture dans ce cas. Mon exemple de code est une version extrêmement simplifiée du code réel - votre solution proposée ne correspondra malheureusement au cas réel. Mais merci beaucoup pour l'explication de la fermeture.



2
votes

Si vous souhaitez que les données persistent uniquement pour la demande actuelle, utilisez httpcontext.items : http://msdn.microsoft.com/fr- US / Bibliothèque / System.Web.httpContext.items.aspx

Si vous souhaitez que les données persistent pour la session actuelle de l'utilisateur (en supposant que vous disposez d'un état de session activé), utilisez httpcontext.session : http://msdn.microsoft.com/fr- US / Bibliothèque / System.Web.httpcontext.session.aspx


0 commentaires