Nuestro team de trabajo ha estado mucho tiempo buscando para dar solución a tu pregunta, te ofrecemos la soluciones así que deseamos que te sea de mucha ayuda.
Solución:
HttpContext.Current obtiene el contexto actual por Thread (investigué la implementación directamente).
Sería más correcto decir que HttpContext
se aplica a un hilo; o un hilo “entra” en el HttpContext
.
No es posible usar HttpContext.Current dentro de una tarea asíncrona, porque puede ejecutarse en otro subproceso.
De nada; el comportamiento predeterminado de async
/await
se reanudará en un hilo arbitrario, pero ese hilo entrará en el contexto de solicitud antes de reanudar su async
método.
Él key a este es el SynchronizationContext
. Tengo un artículo de MSDN sobre el tema si no está familiarizado con él. UN SynchronizationContext
define un “contexto” para una plataforma, siendo los más comunes los contextos de la interfaz de usuario (WPF, WinPhone, WinForms, etc.), el contexto del grupo de subprocesos y el contexto de solicitud de ASP.NET.
El contexto de solicitud de ASP.NET administra HttpContext.Current
así como algunas otras cosas como la cultura y la seguridad. Los contextos de la interfaz de usuario están estrechamente asociados con un solo hilo (la Subproceso de interfaz de usuario), pero el contexto de solicitud de ASP.NET no está vinculado a un subproceso específico. Sin embargo, solo permitirá un hilo en el contexto de la solicitud. a la vez.
La otra parte de la solución es cómo async
y await
trabaja. Yo tengo un async
intro en mi blog que describe su comportamiento. En resumen, await
por defecto capturará el contexto actual (que es SynchronizationContext.Current
a menos que sea null
), y use ese contexto para reanudar el async
método. Asi que, await
está capturando automáticamente el ASP.NET SynchronizationContext
y reanudará la async
método dentro de ese contexto de solicitud (preservando así la cultura, la seguridad y la HttpContext.Current
).
Si tu await
ConfigureAwait(false)
entonces estás diciendo explícitamente await
para no capturar el contexto.
Tenga en cuenta que ASP.NET tuvo que cambiar su SynchronizationContext
trabajar limpiamente con async
/await
. Debe asegurarse de que la aplicación esté compilada con .NET 4.5 y también se dirija explícitamente a 4.5 en su web.config; este es el valor predeterminado para los proyectos nuevos de ASP.NET 4.5, pero debe configurarse explícitamente si actualizó un proyecto existente de ASP.NET 4.0 o anterior.
Puede asegurarse de que estas configuraciones sean correctas ejecutando su aplicación contra .NET 4.5 y observando SynchronizationContext.Current
. Si esto es AspNetSynchronizationContext
, entonces eres bueno; si es LegacyAspNetSynchronizationContext
entonces la configuración es incorrecta.
Siempre que la configuración sea correcta (y esté utilizando ASP.NET 4.5 AspNetSynchronizationContext
), entonces puede usar con seguridad HttpContext.Current
después de un await
sin preocuparte por eso.
Estoy usando una API web, que usa la metodología async/await.
también usando
1) HttpContext.Current.Server.MapPath
2) System.Web.HttpContext.Current.Request.ServerVariables
Esto funcionó bien durante una buena cantidad de tiempo y se rompió repentinamente sin cambiar el código.
Pasando mucho tiempo volviendo a versiones anteriores anteriores, encontré el que faltaba key causa el problema.
< httpRuntime targetFramework="4.5.2" /> under system.web
No soy un experto técnicamente. Pero sugiero agregar el key a su configuración web y darle un VAMOS.
Encontré un artículo muy bueno que describe exactamente este problema: http://byterot.blogspot.cz/2012/04/aspnet-web-api-series-part-3-async-deep.html?m=1
El autor investigó profundamente cómo se llama al método ExecuteAsync en el marco WebApi y llegó a esta conclusión:
Las acciones de la API web de ASP.NET (y todos los métodos de canalización) se llamarán de forma asincrónica solo si devuelve una tarea o una tarea
Lo que entendí del artículo es que los métodos de acción se llaman sincrónicamente, pero es la decisión de la persona que llama.
Creé una pequeña aplicación de prueba para este propósito, algo como esto:
public class ValuesController : ApiController
public object Get(string clientId, string specialValue)
HttpRequest staticContext = HttpContext.Current.Request;
string staticUrl = staticContext.Url.ToString();
HttpRequestMessage dynamicContext = Request;
string dynamicUrl = dynamicContext.RequestUri.ToString();
return new one = staticUrl, two = dynamicUrl;
y una versión asíncrona que regresa async Task
Traté de hacer un pequeño ataque de DOS con jquery y no pude determinar ningún problema hasta que usé await Task.Delay(1).ConfigureAwait(false);
lo cual es obvio que fallaría.
Lo que saqué del artículo es que el problema es muy complicado y el cambio de subproceso puede ocurrir cuando se usa el método de acción asíncrono, por lo que definitivamente es NO una buena idea usar HttpContext.Current en cualquier parte del código llamado desde los métodos de acción. Pero como el controlador se crea sincrónicamente, usar HttpContext.Current en el constructor y también en la inyección de dependencia está bien.
Cuando alguien tenga otra explicación a este problema por favor corríjame ya que este problema es muy complicado y todavía no estoy 100% convencido.
descargo de responsabilidad:
- Ignoro por ahora el problema de Web-Api autohospedado sin IIS, donde HttpContext.Current probablemente no funcionaría de todos modos. Ahora confiamos en IIS.
Si te gustó nuestro trabajo, tienes la habilidad dejar un ensayo acerca de qué te ha impresionado de esta división.