2012-09-02 12 views
5

Tengo un IHttpHandler que creo que se puede beneficiar de la reutilización, porque es costoso de configurar y es seguro para la ejecución de subprocesos. Pero se está creando un nuevo controlador para cada solicitud. Mi controlador no se está reutilizando.IHttpHandler IsReusable, pero no se vuelve a utilizar

El siguiente es mi caso de prueba simple, sin la configuración costosa. Este caso simple demuestra mi problema:

public class MyRequestHandler : IHttpHandler 
{ 
    int nRequestsProcessed = 0; 

    public bool IsReusable 
    { 
     get { return true; } 
    } 

    public void ProcessRequest(HttpContext context) 
    { 
     nRequestsProcessed += 1; 
     Debug.WriteLine("Requests processed by this handler: " + nRequestsProcessed); 
     context.Response.ContentType = "text/plain"; 
     context.Response.Write("Hello World"); 
    } 
} 

Requests processed by this handler: 1 
Requests processed by this handler: 1 
Requests processed by this handler: 1 
Requests processed by this handler: 1... at least 100 times. I never see > 1. 

¿Entiendo mal cómo funciona IsReusable? ¿Hay algo más que pueda vencer la reutilización? Mi controlador está siendo llamado desde una aplicación de Silverlight si eso hace alguna diferencia.

+0

¿Cómo estás? Conexión del controlador a su aplicación? A través de web.config o programáticamente? – Jacob

+0

Esta es mi primera aplicación de este tipo. Creé un nuevo proyecto de sitio web ASP.NET en Visual Studio. Para ejecutar el servidor, estoy ejecutando Debug desde Visual Studio. –

+0

Pregunto cómo ha configurado 'MyRequestHandler' para ejecutar. Por ejemplo, ¿está configurado en su web.config, o tiene un código en 'Global.asax' que lo registra? – Jacob

Respuesta

3

IsReusable no es una garantía.

Simplemente refactorice su controlador y ponga todo el estado de la solicitud cruzada en una clase diferente. Sepa claramente el estado de solicitud cruzada en una aplicación web en mejores prácticas de todos modos porque es peligroso.

+0

Mi configuración costosa implica asignar hasta 100 MB de memoria, y digamos que no se puede diseñar mejor, por lo que la asignación es inevitable. No quiero volver a asignar 100 MB por cada solicitud. ¿Qué "clase diferente" podría usar para persistir ese puntero de memoria, para que se pueda acceder por múltiples solicitudes (o por múltiples manejadores)? –

+0

Simplemente use una variable estática que apunte a una instancia de su clase de estado. O póngalo en el diccionario de aplicaciones http. Cualquier tipo de almacenamiento estático servirá (asegúrate de que sea seguro para subprocesos, por cierto). – usr

+1

Buena respuesta. Gracias. –

1

Si es seguro para subprocesos, puede ir mejor que reutilizar de todos modos.

Cuando IsReusable true devuelve a continuación: Se crea

  1. En primer lugar una instancia del manejador.
  2. Se llama ProcessRequest.
  3. Es puede ponerse en una piscina para usar de nuevo.

Esto significa que podría reducir los costos de configuración repetidos, pero no necesariamente (sin garantía) y no completamente: si hay varias llamadas concurrentes al mismo URI, entonces será necesario que haya varios controladores creado para manejarlos al mismo tiempo.

Lo bueno de este enfoque es que (cuando se produce la agrupación), los controladores no tienen que ser seguros para subprocesos.

Sin embargo, ya que es suyo, podemos hacerlo mejor en una de dos formas.

Una, es poner toda su funcionalidad en otra clase. Entonces el controlador puede ser una clase delgada donde ProcessRequest pasa a una instancia estática de ese.

Del mismo modo, podemos hacer esto con su clase actual usando un IHttpHandlerFactory:

public class MyRequestHandlerFactory : IHttpHandlerFactory 
{ 
    private static MyRequestHandler SingletonHandler = new MyRequestHandler(); 
    IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) 
    { 
    return SingletonHandler; 
    } 
    void ReleaseHandler(IHttpHandler handler) 
    { 
    //do nothing 
    } 
} 

Con la clase anterior, sólo puede cambiar el web.config para referirse a MyRequestHandlerFactory donde actualmente se refiere a MyRequestHandler y Funcionará perfectamente.

(A menos que usted no es realmente tan seguro para subprocesos como se pensaba, en cuyo caso - oopsie)

Cuestiones relacionadas