Comment : créer un gestionnaire HTTP asynchrone
Mise à jour : novembre 2007
Cette procédure pas à pas illustre la création d'un gestionnaire HTTP asynchrone. Les gestionnaires HTTP asynchrones vous permettent de démarrer un processus externe (tel qu'un appel de méthode à un serveur distant), tout en poursuivant leur traitement. Le gestionnaire peut poursuivre ses tâches sans avoir à attendre la fin du processus externe.
Pendant le traitement d'un gestionnaire HTTP asynchrone, ASP.NET replace le thread qui serait en principe utilisé pour le processus externe dans le pool de threads, jusqu'à ce que le gestionnaire reçoive un rappel du processus externe. Cela permet d'éviter le blocage du thread et d'améliorer les performances, car seul un nombre limité de threads peut être exécuté simultanément. Si plusieurs utilisateurs demandent des gestionnaires HTTP synchrones qui dépendent de processus externes, le système d'exploitation peut rapidement manquer de threads, beaucoup d'entre eux étant bloqués, en attente d'un processus externe.
L'exemple utilisé dans cette procédure pas à pas montre un gestionnaire HTTP asynchrone qui traite des demandes pour les fichiers avec l'extension de nom de fichier .SampleAsync dans une application ASP.NET. L'exemple illustre le code correspondant au gestionnaire et montre comment mapper l'extension .SampleAsync au gestionnaire dans ASP.NET. Il montre également comment mapper l'extension .SampleAsync à ASP.NET dans IIS, afin que ce dernier transmette les demandes se terminant par .SampleAsync à ASP.NET.
Pour plus d'informations sur la manière dont l'exécution ASP.NET interagit avec IIS 6.0, consultez Vue d'ensemble du cycle de vie des applications ASP.NET pour IIS 5.0 et 6.0. Pour plus d'informations sur l'intégration ASP.NET avec IIS 7.0, consultez Vue d'ensemble du cycle de vie des applications ASP.NET pour IIS 7.0.
Cette procédure pas à pas décrit notamment les tâches suivantes :
Création du code pour une classe de gestionnaire HTTP. La classe doit implémenter la méthode ProcessRequest et la propriété IsReusable.
Inscription du gestionnaire dans le fichier Web.config et mappage de l'extension de nom de fichier .SampleAsync à celui-ci.
Mappage de l'extension de nom de fichier .sample à ASP.NET dans IIS.
Composants requis
Pour exécuter cette procédure pas à pas, vous devez disposer des composants suivants :
Visual Studio ou Visual Web Developer ;
Un site Web ASP.NET que vous pouvez exécuter à l'aide des services IIS ;
IIS 6.0 ou IIS 7.0.
Création d'une classe de gestionnaire HTTP asynchrone
Pour commencer, vous allez créer une classe qui implémente le gestionnaire asynchrone.
Pour créer la classe de gestionnaire HTTP HelloWorldAsyncHandler
Si le site Web avec lequel vous travaillez ne comporte pas de dossier App_Code, créez-en un sous la racine du site.
Dans le répertoire App_Code, créez une classe nommée HelloWorldAsyncHandler et ajoutez le code suivant au fichier de classe :
Imports Microsoft.VisualBasic Imports System.Web Imports System.Threading Public Class HelloWorldAsyncHandler Implements IHttpAsyncHandler Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable Get Return False End Get End Property Public Function BeginProcessRequest( _ ByVal context As System.Web.HttpContext, _ ByVal cb As System.AsyncCallback, _ ByVal extraData As Object) _ As System.IAsyncResult _ Implements System.Web.IHttpAsyncHandler.BeginProcessRequest context.Response.Write("<p>Begin IsThreadPoolThread is " _ & Thread.CurrentThread.IsThreadPoolThread & "</p>" & vbCrLf) Dim asynch As New AsynchOperation(cb, context, extraData) asynch.StartAsyncWork() Return asynch End Function Public Sub EndProcessRequest(ByVal result As _ System.IAsyncResult) _ Implements System.Web.IHttpAsyncHandler.EndProcessRequest End Sub Public Sub ProcessRequest(ByVal context _ As System.Web.HttpContext) _ Implements System.Web.IHttpHandler.ProcessRequest Throw New InvalidOperationException() End Sub End Class Class AsynchOperation Implements IAsyncResult Private _completed As Boolean Private _state As [Object] Private _callback As AsyncCallback Private _context As HttpContext ReadOnly Property IsCompleted() As Boolean _ Implements IAsyncResult.IsCompleted Get Return _completed End Get End Property ReadOnly Property AsyncWaitHandle() As WaitHandle _ Implements IAsyncResult.AsyncWaitHandle Get Return Nothing End Get End Property ReadOnly Property AsyncState() As [Object] _ Implements IAsyncResult.AsyncState Get Return _state End Get End Property ReadOnly Property CompletedSynchronously() As Boolean _ Implements IAsyncResult.CompletedSynchronously Get Return False End Get End Property Public Sub New(ByVal callback As AsyncCallback, _ ByVal context As HttpContext, _ ByVal state As [Object]) _callback = callback _context = context _state = state _completed = False End Sub Public Sub StartAsyncWork() ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf StartAsyncTask), Nothing) End Sub Private Sub StartAsyncTask(ByVal workItemState As [Object]) _context.Response.Write("<p>Completion IsThreadPoolThread is " & Thread.CurrentThread.IsThreadPoolThread & "</p>" & vbCrLf) _context.Response.Write("Hello World from Async Handler!") _completed = True _callback(Me) End Sub 'StartAsyncTask End Class 'AsynchOperation
using System; using System.Web; using System.Threading; class HelloWorldAsyncHandler : IHttpAsyncHandler { public bool IsReusable { get { return false; } } public HelloWorldAsyncHandler() { } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) { context.Response.Write("<p>Begin IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + "</p>\r\n"); AsynchOperation asynch = new AsynchOperation(cb, context, extraData); asynch.StartAsyncWork(); return asynch; } public void EndProcessRequest(IAsyncResult result) { } public void ProcessRequest(HttpContext context) { throw new InvalidOperationException(); } } class AsynchOperation : IAsyncResult { private bool _completed; private Object _state; private AsyncCallback _callback; private HttpContext _context; bool IAsyncResult.IsCompleted { get { return _completed; } } WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } } Object IAsyncResult.AsyncState { get { return _state; } } bool IAsyncResult.CompletedSynchronously { get { return false; } } public AsynchOperation(AsyncCallback callback, HttpContext context, Object state) { _callback = callback; _context = context; _state = state; _completed = false; } public void StartAsyncWork() { ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null); } private void StartAsyncTask(Object workItemState) { _context.Response.Write("<p>Completion IsThreadPoolThread is " + Thread.CurrentThread.IsThreadPoolThread + "</p>\r\n"); _context.Response.Write("Hello World from Async Handler!"); _completed = true; _callback(this); } }
Le code implémente la méthode BeginProcessRequest. La méthode écrit une chaîne dans la propriété Response de l'objet HttpContext actuel, crée une nouvelle instance de la classe AsyncOperation et appelle la méthode StartAsyncWork. La méthode StartAsyncWork ajoute ensuite le délégué StartAsyncTask à l'objet ThreadPool. Lorsqu'un thread devient disponible, la méthode StartAsyncTask est appelée et écrit une autre chaîne dans la propriété Response. La tâche se termine alors par un appel du délégué AsyncCallback.
Inscription du gestionnaire HTTP personnalisé dans IIS 6.0
Après avoir créé la classe de gestionnaire HTTP personnalisée, vous devez l'enregistrer dans le fichier Web.config de l'application. Cela permet à ASP.NET de rechercher le gestionnaire lorsque des demandes de ressources dont l'URL se termine par .SampleAsync sont effectuées.
Différentes procédures permettent d'inscrire un gestionnaire, selon la version d'IIS utilisée (IIS 6.0 ou IIS 7.0). Cette section décrit comment inscrire un gestionnaire dans IIS 6.0. La section suivante décrit comment inscrire un gestionnaire dans IIS 7.0.
Pour inscrire le gestionnaire dans IIS 6.0
Si le site Web ne possède pas de fichier Web.config, créez-en un à la racine du site.
Ajoutez au fichier Web.config le balisage en surbrillance suivant :
<configuration> <system.web> <httpHandlers> <add verb="*" path="*.SampleAsync" type="HelloWorldAsyncHandler"/> </httpHandlers> </system.web> </configuration>
L'élément de configuration inscrit le gestionnaire HelloWorldAsyncHandler comme gestionnaire des demandes se terminant par .SampleAsync.
Enregistrez un mappage d'extension de fichier pour l'extension de nom de fichier .SampleAsync à l'aide d'Gestionnaire des services IIS. Pour plus d'informations, consultez Comment : configurer une extension du gestionnaire HTTP dans IIS.
Inscription du gestionnaire HTTP personnalisé dans IIS 7.0
Dans IIS 7.0, une application peut s'exécuter en mode classique ou intégré. En mode classique, le traitement des demandes est fortement similaire à celui appliqué dans IIS 6.0. En mode intégré, IIS 7.0 gère les demandes à l'aide d'un pipeline qui lui permet de partager demandes, modules et autres fonctionnalités avec ASP.NET.
Pour IIS 7.0, l'inscription de gestionnaire requiert d'inscrire le gestionnaire soit dans le fichier Web.config, soit dans Gestionnaire des services IIS. L'administration étant centralisée dans IIS 7.0, toute modification apportée dans le fichier Web.config d'une application est répercutée dans l'interface Gestionnaire des services IIS pour l'application et inversement. Dans les procédures qui suivent, les gestionnaires sont inscrits dans le fichier Web.config.
Différentes procédures permettent d'inscrire le gestionnaire dans IIS 7.0 en mode classique et en mode intégré. Suivez la procédure correspondant au mode IIS que vous utilisez.
Pour inscrire le gestionnaire dans IIS 7.0 en mode classique
Si le site Web ne possède pas de fichier Web.config, créez-en un à la racine du site.
Ajoutez l'élément en surbrillance suivant à votre fichier Web.config.
Remarque : Substituez le chemin d'accès correct au fichier aspnet_isapi.dll. Le fichier .dll se trouve dans le dossier où le .NET Framework est installé. Par défaut, il s'agit du chemin suivant : C:\WINDOWS\Microsoft.NET\Framework\version.
<configuration> <system.web> <httpHandlers> <add verb="*" path="*.SampleAsync" type="HelloWorldAsyncHandler"/> </httpHandlers> </system.web> <system.webServer> <handlers> <add verb="*" path="*.SampleAsync" name="HelloWorldAsyncHandler" type="HelloWorldAsyncHandler" modules="IsapiModule"/> scriptProcessor="%path%\aspnet_isapi.dll" </handlers> </system.webServer> </configuration>
L'élément de configuration inscrit le gestionnaire personnalisé par nom de classe et mappe l'extension de nom de fichier .SampleAsync à ce gestionnaire.
Remarque : Parce que vous inscrivez une extension de nom de fichier personnalisée, l'inscription du gestionnaire se fait à la fois dans la section handlers et dans la section httpHandlers. En mode classique, pour la compatibilité descendante, le gestionnaire est spécifié comme un module ISAPI à l'aide de l'attribut modules. Le chemin d'accès du dll ISAPI ASP.NET est spécifié à l'aide de l'attribut scriptProcessor. L'attribut name est requis dans la section handlers.
Pour inscrire le gestionnaire dans IIS 7.0 en mode intégré
Si le site Web ne possède pas de fichier Web.config, créez-en un à la racine du site.
Ajoutez l'élément en surbrillance suivant à votre fichier Web.config.
<configuration> <system.webServer> <handlers> <add verb="*" path="*.SampleAsync" name="HelloWorldAsyncHandler" type="HelloWorldAsyncHandler"/> </handlers> </system.webServer> </configuration>
L'élément de configuration inscrit le gestionnaire personnalisé par nom de classe et mappe l'extension de nom de fichier .SampleAsync à ce gestionnaire.
Remarque : L'inscription se fait dans la section handlers, mais pas dans la section httpHandlers. L'attribut name est requis.
Test du gestionnaire HTTP personnalisé
Après avoir créé et inscrit le gestionnaire HTTP personnalisé, vous pouvez le tester.
Pour tester votre gestionnaire HTTP personnalisé
Naviguez jusqu'à l'application et entrez dans le navigateur une URL qui se termine par .SampleAsync.
Le texte défini dans la classe HelloWorldAsyncHandler est affiché.
Voir aussi
Tâches
Procédure pas à pas : création d'un gestionnaire HTTP synchrone
Concepts
Vue d'ensemble du cycle de vie des applications ASP.NET pour IIS 5.0 et 6.0