2012-05-11 14 views
5

Hoy me encontré con un problema extraño que no tenía sentido para mí. He aquí un resumen:System.Web.HttpContext.Current se anula después de buscar un Caché

dentro de un método, puedo comprobar si hay un elemento de la caché de la siguiente manera:

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

    //... 
} 

Aquí, el HttpContext.Current no es nulo como se espera dentro de una aplicación ASP.NET. Entonces, dentro del método cacheRatesStatusObject, puedo comprobar si HttpContext.Current es nulo o no de la siguiente manera:

private void cacheRatesStatusObject(RatesStatus ratesStatus) { 

    //... 

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

    //... 
} 

y es nula allí. No tengo idea de lo que está pasando aquí. ¿Alguna idea?

+1

me señaló que su método está marcado 'async'. Solo para estar seguro, donde sea que llames a este método, estás haciendo 'esperar' en alguna parte antes de que la 'Respuesta' se envíe de vuelta al cliente y se cierre, ¿verdad? De lo contrario, podría ser simplemente una condición de carrera, donde la 'Respuesta 'se devuelve y elimina antes de llegar a esta línea, pero todavía está disponible en la línea superior. –

+0

@GuthMD Sí, utilicé 'await' en algún lugar dentro del método. Este debe ser el problema. – tugberk

Respuesta

4

Cuando utiliza async/await, el subproceso que maneja la solicitud marca la solicitud como incompleta y luego regresa al ASP.NET thread pool. Cuando el awaitable se completa más tarde, se asigna otro subproceso para ejecutar el resto del método, sin embargo, HttpContext no se migra a través de subprocesos, por eso se obtiene una referencia nula cuando se llama al método await.

Puede pasar una referencia de la HttpContext al método esperan, algo como esto:

await cacheRatesStatusObject(HttpContext.Current, ratesStatus); 

Sin embargo se debe tener mucho cuidado de hacer frente a las condiciones de concurrencia y de la raza, por ejemplo, si el hilo esperan ser encierra un recurso y otro subproceso de solicitud intenta usarlo, su grupo de subprocesos se dispara. La mayoría de las personas resuelve esto creando nuevos objetos y pasándolos a hilos paramaterizados en lugar de pasar una referencia de HttpContext a través de hilos.

+0

En realidad 'HttpContext.Current' no es nulo después de esperar. Solo es nulo en el método asincrónico. Vea esta pregunta: http://aspnetwebstack.codeplex.com/discussions/359012 – Aliostad

0

No se anula.

El HttpContext solo se almacena en modo 'hilo estático'.

Según lo sugerido por la otra respuesta, simplemente pase la instancia.

+0

Sí, me di cuenta de eso. Obtengo una instancia de esto antes de la llamada asincrónica: 'var httpContext = HttpContext.Current;' luego, en el proceso, trabajo con esta variable local. – tugberk

+0

Esto no tiene mucho sentido. ¿Por qué el contexto del hilo no se copia? – Aliostad

+0

@Aliostad: así es como funciona. Los otros hilos que sirven otras solicitudes compartirían el mismo estado. – leppie

Cuestiones relacionadas