89 votes

Puis-je utiliser des threads pour effectuer des tâches de longue durée sur IIS?

Dans un ASP.Net l'application, l'utilisateur clique sur un bouton sur la page web, et ce alors instancie un objet sur le serveur via le gestionnaire d'événement et appelle une méthode sur l'objet. La méthode va à un système externe pour faire des choses et cela pourrait prendre un certain temps. Donc, ce que je voudrais faire est de lancer cet appel de méthode dans un autre thread, donc je peux redonner le contrôle à l'utilisateur avec "Votre demande a été soumise". Je suis assez satisfait pour ce faire, comme le feu et oublier, mais il serait encore mieux si l'utilisateur pouvait continuer à l'interrogation de l'objet d'état.

Ce que je ne sais pas si IIS permet à mon fils pour continuer à fonctionner, même si l'utilisateur de la session expire. Imaginez, l'utilisateur déclenche l'événement et nous instancier l'objet sur le serveur et le feu de la méthode dans un nouveau thread. L'utilisateur est heureux avec les "Votre demande a été soumise" message et ferme son navigateur. Finalement, ce utilisateurs session sur IIS, mais le thread peut encore être en cours d'exécution, faire du travail. Va IIS permettre le fil de continuer à courir ou va le tuer et de disposer de l'objet une fois la session de l'utilisateur expire?

EDIT: à Partir des réponses et des commentaires, je comprends que la meilleure façon de le faire est de déplacer le long cours de traitement à l'extérieur de l'IIS. En dehors de tout le reste, ce prix avec le domaine d'application de recyclage problème. Dans la pratique, j'ai besoin d'obtenir la version 1 hors-sol, dans un temps limité et doit travailler à l'intérieur d'un cadre, de sorte voudrais éviter de la couche de service, d'où le désir de se faire renvoyer du fil à l'intérieur de IIS. Dans la pratique, la "longue course" ici ne sont que quelques minutes et la concurrence d'accès sur le site web sera faible, donc ça devrait être ok. Mais, la prochaine version sera certainement besoin de se diviser en un service distinct de la couche.

67voto

Bryan Batchelder Points 2744

Vous pouvez accomplir ce que vous voulez, mais il est généralement une mauvaise idée. Plusieurs ASP.NET blog et CMS moteurs de cette approche, parce qu'ils veulent être installable sur un hébergement mutualisé système et de ne pas prendre une dépendance sur un service windows qui doit être installé. Généralement, ils entreprennent un long thread en cours d'exécution dans le Mondial.asax au démarrage de l'application, et ont de ce thread processus de mise en file d'attente des tâches.

En plus de réduire les ressources disponibles pour IIS/ASP.NET pour traiter les demandes, vous aussi vous avez des problèmes avec le fil d'être tué lorsque le domaine d'application est recyclé, et puis vous avez à traiter avec la persistance de la tâche alors qu'il est en vol, ainsi que le démarrage du travail de sauvegarder lorsque le domaine d'application est de retour.

Gardez à l'esprit que dans de nombreux cas, le domaine d'application est recyclé automatiquement à un intervalle par défaut, ainsi que si vous mettez à jour le site web.config, etc.

Si vous pouvez gérer la persistance et les aspects transactionnels de votre fil d'être tué à tout moment, alors vous pouvez obtenir autour de le domaine d'application de recyclage des processus externe qui fait une demande sur votre site à un certain intervalle, de sorte que si le site est recyclé vous avez la garantie d'avoir repris automatiquement au bout de X minutes.

Encore une fois, c'est généralement une mauvaise idée.

EDIT: Voici quelques exemples de cette technique dans l'action:

Serveur de communauté: en Utilisant les Services Windows vs Thread d'arrière-plan pour Exécuter du Code à des Intervalles Réguliers La création d'un Thread d'arrière-plan Lorsque le Site Démarre pour la Première fois

7voto

senfo Points 8611

Vous ne voulez pas utiliser un thread du pool de threads IIS pour cette tâche, car il laisserait ce thread impossible de traiter les demandes futures. Vous pourriez regarder dans les Pages Asynchrones dans ASP.NET 2.0, mais ce ne serait vraiment pas la bonne réponse, soit. Au lieu de cela, ce qu'il sonne comme vous pourriez bénéficier de recherche dans Microsoft Message Queuing. Essentiellement, vous ajoutez les détails de la tâche de la file d'attente et un autre processus en arrière-plan (peut-être un Service Windows) serait en charge de la réalisation de cette tâche. Mais la ligne de fond est que le processus d'arrière-plan est complètement isolé de IIS.

5voto

Daniel Points 51

Il y a un bon fil et un exemple de code ici: http://forums.asp.net/t/1534903.aspx?PageIndex=2

J'ai même joué avec l'idée d'appeler un garder vivante la page sur mon site depuis le thread pour aider à garder l'application de la piscine en vie. Gardez à l'esprit que si vous utilisez cette méthode que vous avez vraiment besoin d'une bonne récupération de la manipulation, parce que l'application pourrait recycler à tout moment. Comme beaucoup l'ont mentionné, ce n'est pas la bonne approche si vous avez accès à d'autres options de service, mais pour l'hébergement mutualisé, cela peut être l'un de vos seules options.

Pour aider à garder l'application de la piscine en vie, vous pouvez faire une demande à votre propre site tandis que le thread est en cours de traitement. Cela peut aider à garder le pool d'application vivante, si votre processus exécute un long moment.

string tempStr = GetUrlPageSource("http://www.mysite.com/keepalive.aspx");


    public static string GetUrlPageSource(string url)
    {
        string returnString = "";

        try
        {
            Uri uri = new Uri(url);
            if (uri.Scheme == Uri.UriSchemeHttp)
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
                CookieContainer cookieJar = new CookieContainer();

                req.CookieContainer = cookieJar;

                //set the request timeout to 60 seconds
                req.Timeout = 60000;
                req.UserAgent = "MyAgent";

                //we do not want to request a persistent connection
                req.KeepAlive = false;

                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                Stream stream = resp.GetResponseStream();
                StreamReader sr = new StreamReader(stream);

                returnString = sr.ReadToEnd();

                sr.Close();
                stream.Close();
                resp.Close();
            }
        }
        catch
        {
            returnString = "";
        }

        return returnString;
    }

2voto

David Basarab Points 25852

Pouvez-vous créer un service Windows pour effectuer cette tâche? Ensuite, utilisez .NET Remoting à partir du serveur Web pour appeler le service Windows afin d'effectuer l'action. Si tel est le cas, c'est ce que je ferais.

Cela éliminerait le besoin de faire appel à IIS et limiterait une partie de sa puissance de traitement.

Sinon, je forcerais l'utilisateur à rester assis pendant que le processus est terminé. De cette façon, vous vous assurez qu'il est terminé et non tué par IIS.

2voto

Olly Points 2982

Il semble exister un moyen pris en charge d’héberger des travaux de longue durée dans IIS. Les services de flux de travail semblent conçus pour cela, notamment avec Windows Server AppFabric . La conception permet le recyclage du pool d'applications en prenant en charge la persistance automatique et la reprise du travail de longue durée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X