2010-02-05 19 views
5

Actualmente estoy desarrollando un HttpHandler personalizado (para comprimir/combinar CSS, pero eso no importa para esta pregunta).Patrón para HttpHandler asincrónico reutilizable

Empecé con un HttpHandler sencillo reutilizable = verdadero sincrónico, como todos sabemos.

Ahora estoy tratando de mejorarlo a un controlador asincrónico (ya que utiliza la funcionalidad IO y se usa en un sitio web muy ocupado).

Mi primer intento (y esto parece funcionar bien):

Action<HttpContext> asyncProcessRequest; 

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) 
{ 
    asyncProcessRequest = new Action<HttpContext>(ProcessRequest); 
    return asyncProcessRequest.BeginInvoke(context, cb, extraData); 
} 

public void EndProcessRequest(IAsyncResult result) 
{ 
    asyncProcessRequest.EndInvoke(result); 
} 

public virtual void ProcessRequest(HttpContext context) 
{ 
    // real work 
} 

Ésta es una HttpHandler no reutilizables (como por lo que leí, IsReusable debe ser falsa, porque este controlador tiene el estado (el asyncProcessRequest . campo)

Ahora quiero hacer esta reutilizable Así que mi primera idea era crear un diccionario de IAsyncResult/acción como esta:.

IDictionary<IAsyncResult, Action<HttpContext>> asyncProcessRequests; 

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) 
{ 
    if (asyncProcessRequests == null) 
    { 
     asyncProcessRequests = new Dictionary<IAsyncResult, Action<HttpContext>>(); 
    } 

    var request = new Action<HttpContext>(ProcessRequest); 
    var result = request.BeginInvoke(context, cb, extraData); 
    asyncProcessRequests.Add(result, request); 
    return result; 
} 

public void EndProcessRequest(IAsyncResult result) 
{ 
    Action<HttpContext> action; 
    if (asyncProcessRequests.TryGetValue(result, out action)) 
    { 
     action.EndInvoke(result); 
    } 
} 

¿Es esta una correc t patrón? o estoy lejos?

Parece que funciona (no estoy recibiendo ningún error o comportamiento extraño), pero antes de poner esto a la producción, me gustaría comprobar con alguien que tiene más experiencia que yo al escribir estos controladores HTTP ..

¡Gracias de antemano!

+1

¿Estás seguro de que realmente necesitas comprimir/compactar CSS para todas y cada una de las solicitudes? Tal vez, es mejor hacer esto durante las compilaciones/implementaciones? –

+0

... y/o asegúrese de que se almacena en caché correctamente. – Lucero

+1

el almacenamiento en caché de archivos y archivos se maneja correctamente. Pero esta pregunta es más sobre el patrón httphandler asincrónico/reutilizable ... –

Respuesta

4

En general, para el patrón asíncrono, debe usar el parámetro de estado que pasa al método BeginXxx como último parámetro (lo llamó extraData).

Por lo que es posible que desee crear una clase de ayuda que contenga el (original) extraData, así como el estado adicional que necesite para manejar el fin de la solicitud.

Sin embargo, en su caso específico, creo que no está acelerando nada con el uso del patrón asíncrono. Mientras funciona, básicamente solo agrega sobrecarga, ya que está llamando a un delegado de manera asíncrona, que no hace más que enviar una llamada al grupo de subprocesos para gestionar la llamada. Por lo tanto, siempre y cuando no tenga múltiples delegados ejecutándose simultáneamente a través de llamadas asíncronas, no obtendrá mucho beneficio. Dado que las solicitudes web ya están multiproceso, no creo que esto ayude al rendimiento; por el contrario, corres el riesgo de morir de hambre en el hilo.

El manejo asíncrono correcto y eficiente no es fácil. Puede beneficiarse de ello si realiza tareas asincrónicas inherentes, como leer datos de un archivo o conexión de red, o cuando llama a componentes externos que admiten la invocación asincrónica (como una llamada al servicio web o una base de datos).

+0

Véase también http://geekswithblogs.net/SanjayU/archive/2009/01/06/ihttphandler-vs-ihttpasynchandler.aspx – Lucero

+0

¿Entonces básicamente lo que está diciendo es que debería seguir con un manipulador síncrono reutilizable? –

+3

Sí, si solo planea invocar al delegado de forma asíncrona. Si está haciendo un archivo extenso, una red (incluidas las solicitudes web) o llamadas a bases de datos, considere implementar el patrón asíncrono, de lo contrario, no. Consulte también http://msdn.microsoft.com/en-us/magazine/cc164128.aspx – Lucero

2

Si recuerdo correctamente, IsReusable indica a ASP.NET que su controlador no debe destruirse después de procesar la solicitud y que la misma instancia se puede usar para procesar solicitudes posteriores. Es decir. una instancia del objeto controlador no maneja múltiples solicitudes simultáneamente.

+0

Por lo tanto, no se destruye (las solicitudes posteriores utilizan la misma instancia). Pero también garantiza que no se realicen solicitudes simultáneas en la misma instancia ... Entonces, ¿cómo maneja asp.net la carga alta? ¿Crea más instancias?o ¿espera a que finalice la solicitud actual? –

+0

Dado que la inicialización de su objeto es muy económica, puede que no valga la pena volverla reutilizable. Esto tiene sentido si la creación del controlador http es costosa (por ejemplo, si tiene que inicializarse desde un archivo de configuración o lo que sea). – Lucero

+0

El objetivo de usar IHttpAsyncHandler es devolver el hilo asignado a la solicitud al grupo de subprocesos (los hilos son recursos limitados). Si su controlador http es un objeto liviano y crea instancias rápidamente, creo que no habría un beneficio significativo en el rendimiento con el controlador reutilizable sobre los no reutilizables. – Yaroslav

Cuestiones relacionadas