web-dev-qa-db-fra.com

Accédez à HttpContext.Current à partir de différents threads

J'ai une application C # ASP.NET qui démarre environ 25 threads différents exécutant certaines méthodes dans une classe appelée SiteCrawler.cs.

Dans HttpContext.Current.Session Je veux enregistrer le résultat de la recherche effectuée par l'utilisateur et le présenter à l'utilisateur lorsque tous les threads ont terminé de fonctionner. Mon problème est que le HttpContext.Current l'objet est nul dans les threads générés car il n'y existe pas.

Quelles autres options dois-je pour enregistrer des données spécifiques à l'utilisateur/session sans utiliser de session en raison des limitations lorsque l'application est multithread?

J'ai essayé de chercher dans chaque centimètre de Stackoverflow pour trouver une solution mais sans aucune chance ....

51
Raydk

Dans mon application, il y a beaucoup de code qui utilise HttpContext.Current Et je ne peux pas modifier ce code.

worker.DoWork() de l'exemple ci-dessous utilise ce code. Et je devais l'exécuter dans un thread séparé.

Je suis arrivé à la solution suivante:

 HttpContext ctx = HttpContext.Current;
 Thread t = new Thread(new ThreadStart(() =>
                {
                    HttpContext.Current = ctx;
                    worker.DoWork();
                }));
 t.Start();
 // [... do other job ...]
 t.Join();
71
Dmitry Andrievsky

Jetez un œil à cet article de Fritz Onion: tilisez des threads et créez des gestionnaires asynchrones dans votre code Web côté serveur . C'est assez long, mais votre exigence n'est pas trop banale.

K. Scott Allen a également publié un article un peu plus court sur ce problème: Travailler avec HttpContext.Current

11
Dennis Traub

@Rory a fait un commentaire ci-dessus, que certains objets du HttpContext deviendront nuls même si vous le passez dans le Thread. Cela m'est arrivé avec la propriété User. Donc, à la place, vous pouvez copier l'utilisateur dans le thread CurrentPrincipal comme ceci:

Dans le contexte du contrôleur, enregistrez l'utilisateur:

            _user = HttpContext.Current.User;
            var processThread = new Thread(() => ThreadedCode());
            processThread.Start();

Dans le fil, définissez l'utilisateur "Fil":

    private static void ThreadedCode()
    {
        // Workaround for HttpContext.Current.User being null.
        // Needed for CreatedBy and RevisedBy.
        Thread.CurrentPrincipal = _user;

Notez que le HttpContext ne sera disponible que pour la durée de vie de la demande. Le thread vivra potentiellement beaucoup plus longtemps que la demande, c'est probablement pourquoi vous avez besoin d'un thread en premier lieu! :)

7
Jess

Ajoutez simplement HttpContext.Current au constructeur de votre classe SiteCrawler.cs

public class SiteCrawler
{
     HttpContext context = HttpContext.Current;

    public void Method()
    {
        context.WhateverYouWant
    }
}
4
jjspierx

Vous pouvez l'enregistrer dans la base de données et ensuite, vous pouvez laisser le navigateur de l'utilisateur continuer à se rafraîchir ou utiliser ajax ou utiliser le nouveau signalr pour vérifier si le résultat est déjà écrit en db. J'espère que ça aide.

3
ysrb