Demonstra Passo a passo: Criar um manipulador HTTP assíncrono

Essa explicação passo a passo mostra como criar um manipulador HTTP assíncrono.Manipuladores assíncronos HTTP permitem que você inicie um processo externo (como uma chamada de método a um servidor remoto) enquanto o manipulador continua o processamento.O manipulador pode continuar sem esperar que o processo externo concluir.

Durante o processamento de um manipulador HTTP assíncrono, ASP.NET coloca o segmento que normalmente deve ser usado para o processo externo de volta para o pool de segmento até o manipulador receber um retorno de chamada do processo externo.Isso pode prevenir que o segmento bloqueie e melhora bastante o desempenho, porque somente um número limitado de segmentos podem ser executados simultaneamente.Rapidamente se um número de usuários solicitar manipuladores HTTP síncronos que dependam dos processos externos, o sistema operacional pode executar fora de segmentos pois muitos segmentos são bloqueados e ficam em espera por um processo externo.

O exemplo nessa explicação passo a passo demonstra um manipulador HTTP assíncrono que processa solicitações de arquivos que possuem extensão de nome de arquivo .SampleAsync em um aplicativo ASP.NET.O exemplo mostra o código para o manipulador e, em seguida, como MAP a extensão .SampleAsync para o manipulador no ASP.NET.O exemplo também mostra como mapear a extensão .SampleAsync para o ASP.NET no IIS, para que IIS encaminhe solicitações participante no .SampleAsync para o ASP.NET.

Para obter mais informações sobre como a execução em ASP.NET interage com o IIS 6.0, consulte Ciclo de Vida do Aplicativo ASP.NET uma visão geral para o IIS 5.0 e 6.0.Para obter mais informações sobre a integração do ASP.NET com IIS 7.0, consulte Uma visão geral do Ciclo de Vida do Aplicativo ASP.NET para o IIS 7.0.

Tarefas ilustradas nesta explicação passo a passo incluem o seguinte:

  • Como criar o código para uma classe manipulador HTTP.A classe deve implementar o método ProcessRequest e a propriedade IsReusable.

  • Como registrar o manipulador no arquivo Web.config e mapear a extensão de nome de arquivo .sample para ele.

  • Como mapear a extensão de nome de arquivo .Sample do ASP.NET no IIS.

Pré-requisitos

A fim de concluir este explicação passo a passo, será necessário:

  • Visual Studio ou Visual Web Developer.

  • Um site da Web ASP.NET que possa ser executado por meio do IIS.

  • IIS 6.0 ou IIS 7.0.

Criar uma classe de manipulador HTTP síncrono

Para começar, você criará uma classe que implementa o manipulador assíncrono.

Para criar a classe de um manipulador HTTP HelloWorldAsyncHandler

  1. Se o site da Web em que você estiver trabalhando ainda não tiver uma pasta App_Code, crie uma na raiz do site.

  2. Na pasta App_Code, crie uma classe denominada HelloWorldAsyncHandler e adicione o código a seguir ao arquivo da 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);
        }
    }
    

    No código da página, chame o método BeginProcessRequest.O método grava uma sequência de caracteres para a propriedade Response do objeto atual HttpContext, cria uma nova instância da classe AsyncOperation e chama o método StartAsyncWork.O método StartAsyncWork em seguida adiciona o delegado StartAsyncTask ao objeto ThreadPool.Quando um segmento estiver disponível, o método StartAsyncTask é chamado, no qual gravará outra sequência de caracteres para a propriedade Response.A tarefa então termina invocando o delegado AsyncCallback.

Registrando o manipulador HTTP personalizado no IIS 6,0

Depois de criar a classe manipulador HTTP personalizada, você deve registrá-la no arquivo Web.config do aplicativo.Isso permite que o ASP.NET localize o manipulador quando as solicitações são feitas para os recursos cujo URL termina com .SampleAsync.

Há procedimentos diferentes para registrar o manipulador, dependendo se você estiver trabalhando com o IIS 6.0 ou IIS 7.0.Esta seção descreve como registrar um manipulador no IIS 6.0.A próxima seção descreve como registrar um manipulador no IIS 7.0.

Para registrar o manipulador no IIS 6.0

  1. Se o site da Web ainda não tiver um arquivo Web.config, crie um na raiz do site.

  2. Adicione a seguinte marcação realçada para o arquivo Web.config:

    <configuration>
      <system.web>
        <httpHandlers>      <add verb="*" path="*.SampleAsync"         type="HelloWorldAsyncHandler"/>    </httpHandlers>
      </system.web>
    </configuration>
    

    O elemento de configuração registra o HelloWorldAsyncHandler manipulador de sistema autônomo o manipulador de solicitações que finaliza SampleAsync.

  3. Registre um mapeamento de extensão do aplicativo para a extensão de nome de arquivo .SampleAsync usando Gerenciador do IIS.Para obter mais informações, consulte Como: Configurar uma extensão de manipulador HTTP no IIS.

Registrando o manipulador HTTP personalizado no IIS 7.0

No IIS 7.0, um aplicativo pode executar no modo Clássico ou no modo Integrado.No modo Clássico, as solicitações são processadas da mesma maneira como eles estão no IIS 6.0.No modo integrado, IIS 7.0 gerencia solicitações usando um pipeline que permite que ele compartilhe as solicitações, módulos e outros recursos com o ASP.NET.

Para IIS 7.0, o registro do manipulador requer o registro do manipulador no arquivo Web.config ou no Gerenciador do IIS.Devido a administração centralizada no IIS 7.0, as alterações no arquivo Web.config do aplicativo são refletidas na interface Gerenciador do IIS para o aplicativo e vice-versa.Nos procedimentos a seguir, os manipuladores são registrados no arquivo Web.config.

Há procedimentos diferentes para registrar o manipulador IIS 7.0 sendo executado no modo Clássico e sendo executado no modo Integrado.Siga o procedimento para o modo IIS que você está usando.

Para registrar o manipulador no IIS 7.0 executando no modo clássico

  1. Se o site da Web ainda não tiver um arquivo Web.config, crie um na raiz do site.

  2. Adicione o seguinte elemento realçado ao arquivo Web.config.

    Observação:

    Substitua o caminho correto do arquivo aspnet_isapi.dll.O arquivo .dll está na pasta onde o .NET Framework está instalado.Por padrão, é C:\WINDOWS\Microsoft.NET\Framework\versão.

    <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>
    

    O elemento de configuração registra o manipulador personalizado pelo nome da classe, e ele mapeia a extensão de nome de arquivo .SampleAsync a esse manipulador.

    Observação:

    Porque você estiver inscrevendo uma extensão de nome de arquivo personalizada, você registra o manipulador tanto na seção handlers como na seção httpHandlers.No modo Clássico, para compatibilidade com versões anteriores, o manipulador é especificado como um módulo ISAPI usando o atributo modules.O caminho da DLL ISAPI do ASP.NET é especificado usando o atributo scriptProcessor.O atributo name é necessário na seção handlers.

Para registrar o manipulador no IIS 7.0 executando no modo Integrado

  1. Se o site da Web ainda não tiver um arquivo Web.config, crie um na raiz do site.

  2. Adicione o seguinte elemento realçado ao arquivo Web.config.

    <configuration>
      <system.webServer>
        <handlers>      <add verb="*" path="*.SampleAsync"        name="HelloWorldAsyncHandler"        type="HelloWorldAsyncHandler"/>    </handlers>
      </system.webServer>
    </configuration>
    

    O elemento de configuração registra o manipulador personalizado pelo nome da classe, e ele mapeia a extensão de nome de arquivo .SampleAsync a esse manipulador.

    Observação:

    O registro é feito na seção handlers, e não na seção httpHandlers.O atributo name é necessário.

Teste o manipulador HTTP personalizado

Depois de ter criado e registrado o manipulador HTTP personalizado, você pode testá-lo.

Para testar o manipulador HTTP personalizado

  • Navegue até o aplicativo e digite uma URL em um navegador que termina em .SampleAsync.

    O texto definido na classe HelloWorldAsyncHandler é exibido.

Consulte também

Tarefas

Passo-a-Passo: Criando um Manipulador HTTP Síncrono

Conceitos

Ciclo de Vida do Aplicativo ASP.NET uma visão geral para o IIS 5.0 e 6.0

Outros recursos

Introdução aos manipuladores HTTP