2012-05-11 15 views
5

Ho riscontrato un problema strano oggi che non aveva senso per me. Ecco un riassunto:System.Web.HttpContext.Current si annulla da solo dopo aver controllato per una cache

all'interno di un metodo, ho verificare la presenza di un elemento memorizzato nella cache, come di seguito:

private async Task<RatesStatus> getRatesStatusAsync() { 

    //... 

    if (_currentHttpContext != null) { 

     //Here, I am checking for a Cached item 
     var cachedRatesStatusObj = HttpContext.Current.Cache[Constants.RATESSTATUS_CACHE_KEY_NAME]; 
     if (cachedRatesStatusObj != null) 
      return (RatesStatus)cachedRatesStatusObj; 
    } 

    //... 

    cacheRatesStatusObject(ratesStatus); 

    //... 
} 

Qui, il HttpContext.Current non è nulla come previsto all'interno di un'applicazione ASP.NET. Poi, all'interno del metodo cacheRatesStatusObject, controllo se HttpContext.Current è nulla o non come di seguito:

private void cacheRatesStatusObject(RatesStatus ratesStatus) { 

    //... 

    //Seeing if HttpContext.Current is null or not first. 
    //and it is null here... 
    if (HttpContext.Current == null) 
     return; 

    //... 
} 

ed è nullo lì. Non ho idea di cosa stia succedendo qui. qualche idea?

+1

Ho notato che il metodo è contrassegnato come 'async'. Giusto per sicurezza, ovunque tu stia chiamando questo metodo, stai facendo un 'await' da qualche parte prima che il' Response' venga rispedito al client e chiuso, giusto? Altrimenti potrebbe essere solo una condizione di competizione, in cui il 'Response' viene restituito e disposto prima di arrivare a questa linea, ma ancora disponibile nella riga sopra. –

+0

@GuthMD Sì, ho usato 'await' da qualche parte all'interno del metodo. Questo deve essere il problema. – tugberk

risposta

4

Quando si utilizza async/await, il thread che gestisce la richiesta contrassegna la richiesta come incompleta e quindi torna a ASP.NET thread pool. Quando l'attesa viene completata in un secondo momento, viene assegnato un altro thread per eseguire il resto del metodo, tuttavia HttpContext non viene migrato attraverso i thread, ecco perché si ottiene riferimento null quando si chiama il metodo await.

È possibile passare un riferimento del HttpContext al metodo attendono, qualcosa di simile:

await cacheRatesStatusObject(HttpContext.Current, ratesStatus); 

Tuttavia si dovrebbe essere molto attenti che fare con le condizioni di concorrenza e di gara, ad esempio, se il thread attendono blocca una risorsa e un altro thread di richiesta tenta di usarlo, quindi il pool di thread diventa boom. La maggior parte delle persone risolve questo creando nuovi oggetti e passandoli in thread parametrizzati invece di passare un riferimento di HttpContext attraverso i thread.

+0

In realtà 'HttpContext.Current' non è nullo dopo l'attesa. È nullo solo nel metodo asincrono. Vedi questa domanda: http://aspnetwebstack.codeplex.com/discussions/359012 – Aliostad

0

Non si annulla.

HttpContext viene memorizzato solo in modo "thread static".

Come suggerito dall'altra risposta, basta passare l'istanza.

+0

Sì, l'ho appena capito. Ricevo un'istanza di questo prima della chiamata asincrona: 'var httpContext = HttpContext.Current;' poi più avanti nel processo, lavoro con questa variabile locale. – tugberk

+0

Questo non ha molto senso. Perché il contesto del thread non viene copiato ?? – Aliostad

+0

@Aliostad: è solo il modo in cui funziona. Altrimenti altri thread che servono altre richieste condividono lo stesso stato. – leppie