2010-02-05 24 views
5

Attualmente sto sviluppando un HttpHandler personalizzato (per la compressione/combinazione di CSS, ma non importa per questa domanda).Pattern per HttpHandler asincrono riutilizzabile

Ho iniziato con un semplice reusable = sincrono HttpHandler come tutti sappiamo.

Ora sto provando a migliorarlo con un gestore asincrono (poiché utilizza la funzionalità IO e viene utilizzato su un sito Web molto occupato).

Il mio primo tentativo (e questo sembra funzionare bene):

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 
} 

Questo è un HttpHandler non riutilizzabili (come da quanto ho letto, IsReusable dovrebbe essere falsa, perché questo gestore ha lo stato (l'asyncProcessRequest . campo)

Ora voglio fare questa riutilizzabile Così il mio primo pensiero è stato quello di creare un dizionario di IAsyncResult/Azione in questo modo:.

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); 
    } 
} 

questa è una correc modello? o sono via?

Sembra funzionare (Non ricevo eventuali errori o comportamenti strano), ma prima di mettere questo per la produzione, vorrei verificare con qualcuno che ha più esperienza di me nello scrivere queste gestori HTTP ..

Grazie in anticipo!

+1

Sei sicuro di aver davvero bisogno di comprimere/compattare CSS per ogni singola richiesta? Forse, è meglio farlo durante le build/distribuzioni? –

+0

... e/o assicurati che venga memorizzato correttamente nella cache. – Lucero

+1

Il browser e il caching dei file sono gestiti correttamente. Ma questa domanda riguarda maggiormente il modello httphandler async/riutilizzabile ... –

risposta

4

In generale, per il modello asincrono, è necessario utilizzare il parametro di stato che si passa al metodo BeginXxx come ultimo parametro (lo si è chiamato extraData).

Quindi è possibile creare una classe di supporto contenente lo (originale) extraData e qualsiasi altro stato aggiuntivo necessario per gestire la fine della richiesta.

Tuttavia, nel tuo caso specifico, credo che non stai accelerando nulla con l'uso del modello asincrono. Mentre funziona, fondamentalmente aggiunge solo un sovraccarico, dal momento che stai chiamando un delegato in modo asincrono, che non fa altro che inviare una chiamata al pool di thread per gestire la chiamata. Pertanto, finché non si hanno più delegati in esecuzione simultaneamente tramite chiamate asincrone, non si trarrà alcun vantaggio. Dal momento che le richieste web sono già multithread, non credo che ciò aiuti le prestazioni; al contrario, corri il rischio di morire di fame da threadpool.

La gestione asincrona corretta ed efficiente non è facile. Puoi trarne vantaggio se stai facendo cose intrinsecamente asincrone come leggere dati da un file o una connessione di rete o quando chiami componenti esterni che supportano la chiamata asincrona (come una chiamata al servizio web o un database).

+0

Vedere anche http://geekswithblogs.net/SanjayU/archive/2009/01/06/ihttphandler-vs-ihttpasynchandler.aspx – Lucero

+0

Quindi, in pratica, quello che stai dicendo è che dovrei rimanere con un gestore sincrono riutilizzabile? –

+3

Sì, se si prevede di richiamare il delegato solo in modo asincrono. Se stai facendo file lunghi, rete (comprese le richieste web) o chiamate al database, considera l'implementazione del pattern asincrono, altrimenti piuttosto no. Vedi anche http://msdn.microsoft.com/en-us/magazine/cc164128.aspx – Lucero

2

Se ricordo correttamente IsReusable indica ad ASP.NET che il gestore non deve essere distrutto dopo l'elaborazione della richiesta e che la stessa istanza potrebbe essere utilizzata per elaborare richieste successive. Cioè un'istanza dell'oggetto gestore non gestisce più richieste contemporaneamente.

+0

Quindi non viene distrutto (le richieste successive utilizzano la stessa istanza). Ma garantisce anche che non vengano fatte richieste simultanee sulla stessa istanza ... In che modo asp.net gestisce un carico elevato allora? crea più istanze?o aspetta che la richiesta corrente sia finita? –

+0

Poiché l'inizializzazione del tuo oggetto è molto economica, renderla riutilizzabile potrebbe non valerne la pena. Questo ha senso se la creazione del gestore HTTP è costosa (ad esempio, se deve inizializzarsi da un file di configurazione o qualsiasi altra cosa). – Lucero

+0

Il punto in utilizzare IHttpAsyncHandler è restituire il thread che è stato assegnato alla richiesta al pool di thread (i thread sono risorse limitate). Se il tuo gestore HTTP è un oggetto leggero e si istanzia rapidamente, penso che non ci sarebbe un vantaggio significativo nelle prestazioni con il gestore riusabile su non riutilizzabile. – Yaroslav