Eventos
Campeonato mundial de DataViz de Power BI
14 feb, 16 - 31 mar, 16
Con 4 posibilidades de entrar, podrías ganar un paquete de conferencia y convertirlo en el Live Grand Finale en Las Vegas
Saber másEste explorador ya no se admite.
Actualice a Microsoft Edge para aprovechar las características y actualizaciones de seguridad más recientes, y disponer de soporte técnico.
por Rick Anderson
Este tutorial le enseñará los conceptos básicos de la creación de una aplicación web ASP.NET MVC asincrónica mediante Visual Studio Express 2012 para Web, que es una versión gratuita de Microsoft Visual Studio. También puede usar Visual Studio 2012.
En github https://github.com/RickAndMSFT/Async-ASP.NET/ se proporciona un ejemplo completo para este tutorial
La clase Controller de ASP.NET MVC 4 junto con .NET 4.5 le permite escribir métodos de acción asincrónicos que devuelven un objeto de tipo Task<ActionResult>. En .NET Framework 4 se introdujo un concepto de programación asincrónico denominado Tarea y en ASP.NET MVC 4 se admite Tarea. Las tareas se representan mediante el tipo Task y los tipos relacionados en el espacio de nombres System.Threading.Tasks. .NET Framework 4.5 se basa en esta compatibilidad asincrónica con las palabras clave await y async que hacen que el trabajo con objetos Task sea mucho menos complejo que los enfoques asincrónicos anteriores. La palabra clave await es una abreviatura sintáctica para indicar que un fragmento de código debe esperar de forma asincrónica por otro fragmento de código. La palabra clave async representa una sugerencia que puede usar para marcar métodos como asincrónicos basados en tareas. La combinación de await, asyncy el objetoTask facilita mucho la escritura de código asincrónico en .NET 4.5. El nuevo modelo para métodos asincrónicos se denomina Patrón asincrónico basado en tareas (TAP). En este tutorial se supone que está familiarizado con la programación asincrónica mediante palabras clave await y async, y el espacio de nombres Task.
Para más información sobre el uso de las palabras clave await y async, y el espacio de nombres Task, vea las siguientes referencias.
En el servidor web, .NET Framework mantiene un grupo de subprocesos que se utilizan para dar servicio a las solicitudes de ASP.NET. Cuando se recibe una solicitud, se envía un subproceso del grupo para procesarla. Si la solicitud se procesa de manera sincrónica, el subproceso está ocupado mientras la procesa, de modo que no puede prestar servicio a otra solicitud.
Esto podría no ser un problema, porque se puede crear un grupo de subprocesos lo bastante grande para alojar numerosos subprocesos ocupados. Pero el número de subprocesos del grupo de subprocesos es limitado (el máximo predeterminado para .NET 4.5 es de 5000). En aplicaciones grandes con alta simultaneidad de solicitudes de larga duración, es posible que todos los subprocesos disponibles estén ocupados. Esta situación se denomina colapso de los subprocesos. Cuando se llega a esta situación, el servidor web pone las solicitudes en cola. Si la cola de solicitudes se llena, el servidor web rechaza las solicitudes y muestra el estado HTTP 503 (Servidor muy ocupado). El grupo de subprocesos de CLR tiene limitaciones en las inyecciones de subprocesos nuevos. Si la simultaneidad tiene ráfagas (es decir, el sitio web puede obtener repentinamente un gran número de solicitudes) y todos los subprocesos de solicitud disponibles están ocupados debido a las llamadas de back-end con una latencia alta, la tasa limitada de inyección de subprocesos puede hacer que la aplicación responda muy mal. Además, cada subproceso nuevo que se agrega al grupo de subprocesos tiene sobrecarga (por ejemplo, 1 MB de memoria de pila). Una aplicación web que use métodos sincrónicos para atender llamadas de alta latencia en las que el grupo de subprocesos crece hasta el máximo predeterminado de .NET 4.5 de 5000 subprocesos consumiría aproximadamente 5 GB más de memoria que una aplicación capaz de atender las mismas solicitudes mediante métodos asincrónicos y solo 50 subprocesos. Cuando realiza un trabajo asincrónico, no siempre usa un subproceso. Por ejemplo, al realizar una solicitud de servicio web asincrónica, ASP.NET no usará ningún subproceso entre la llamada al método async y await . El uso del grupo de subprocesos para atender las solicitudes con alta latencia puede provocar una gran superficie de memoria y un uso deficiente del hardware del servidor.
En las aplicaciones web que ven un gran número de solicitudes simultáneas al inicio o tienen una carga con ráfagas (donde la simultaneidad aumenta repentinamente), realizar llamadas de servicio web asincrónicas aumenta la capacidad de respuesta de la aplicación. Una solicitud asincrónica tarda el mismo tiempo en procesarse que una sincrónica. Si una solicitud realiza una llamada de servicio web que necesita dos segundos para completarse, la solicitud tardará dos segundos con independencia de que se procese de manera sincrónica o asincrónica. Pero durante una llamada asincrónica, el subproceso no está ocupado para responder a otras solicitudes mientras espera que se complete la primera. Por tanto, las solicitudes asincrónicas impiden el crecimiento del grupo de subprocesos y las colas de solicitudes cuando hay muchas solicitudes simultáneas que invocan operaciones de larga duración.
En esta sección se muestran las instrucciones para decidir cuándo utilizar métodos de acción sincrónicos o asincrónicos. Se trata de meras instrucciones; debe estudiar individualmente cada aplicación para determinar si los métodos asincrónicos ayudan a mejorar el rendimiento.
En general, use métodos sincrónicos para las condiciones siguientes:
En general, use métodos asincrónicos para las condiciones siguientes:
En el ejemplo descargable se muestra cómo utilizar con eficacia los métodos de acción asincrónicos. El ejemplo proporcionado se ha diseñado para proporcionar una demostración sencilla de la programación asincrónica en ASP.NET MVC 4 con .NET 4.5. El ejemplo no está pensado como una arquitectura de referencia para la programación asincrónica en ASP.NET MVC. El programa de ejemplo llama a ASP.NET Web API que, a su vez, llama a Task.Delay para simular llamadas de servicio web de larga duración. La mayoría de las aplicaciones de producción no mostrarán ventajas tan evidentes del uso de métodos asincrónicos.
Algunas aplicaciones exigen que todos los métodos de acción sean asincrónicos. Con frecuencia, basta con convertir algunos métodos de acción sincrónicos en métodos asincrónicos a fin de obtener la máxima eficacia para la cantidad de trabajo requerida.
Puede descargar la aplicación de ejemplo desde https://github.com/RickAndMSFT/Async-ASP.NET/ en el sitio de GitHub. El repositorio consta de tres proyectos:
Products, Gizmos and Widgets
. Proporciona los datos para el proyecto WebAppAsync y el proyectoMvc4Async.En el código siguiente se muestra el método de acción sincrónicoGizmos
que se usa para mostrar una lista de gizmos. (Para este artículo, un gizmo es un dispositivo mecánico ficticio).
public ActionResult Gizmos()
{
ViewBag.SyncOrAsync = "Synchronous";
var gizmoService = new GizmoService();
return View("Gizmos", gizmoService.GetGizmos());
}
En el código siguiente se muestra el métodoGetGizmos
del servicio gizmo.
public class GizmoService
{
public async Task<List<Gizmo>> GetGizmosAsync(
// Implementation removed.
public List<Gizmo> GetGizmos()
{
var uri = Util.getServiceUri("Gizmos");
using (WebClient webClient = new WebClient())
{
return JsonConvert.DeserializeObject<List<Gizmo>>(
webClient.DownloadString(uri)
);
}
}
}
El métodoGizmoService GetGizmos
pasa un URI a un servicio HTTP de API web de ASP.NET que devuelve una lista de datos de gizmos. El proyecto WebAPIpgw contiene la implementación de la API web gizmos, widget
y los controladores product
.
En la imagen siguiente se muestra la vista de gizmos del proyecto de ejemplo.
En el ejemplo se usan las nuevas palabras clave async y await (disponibles en .NET 4.5 y Visual Studio 2012) para permitir que el compilador sea responsable de mantener las transformaciones complicadas necesarias para la programación asincrónica. El compilador permite escribir código mediante las construcciones de flujo de control sincrónicas de C# y aplica automáticamente las transformaciones necesarias para usar devoluciones de llamada que evitan que los subprocesos estén ocupados.
En el código siguiente se muestra el método sincrónico Gizmos
y el método asincrónico GizmosAsync
. Si el explorador admite el elemento <mark>
de HTML 5, verá los cambios en GizmosAsync
resaltados en color amarillo.
public ActionResult Gizmos()
{
ViewBag.SyncOrAsync = "Synchronous";
var gizmoService = new GizmoService();
return View("Gizmos", gizmoService.GetGizmos());
}
public async Task<ActionResult> GizmosAsync()
{
ViewBag.SyncOrAsync = "Asynchronous";
var gizmoService = new GizmoService();
return View("Gizmos", await gizmoService.GetGizmosAsync());
}
Se han aplicado los siguientes cambios para permitir que GizmosAsync
sea asincrónico.
Task<ActionResult>
para devolver.ActionResult
a Task<ActionResult>
. El tipo de valor devuelto de Task<ActionResult>
representa el trabajo en curso y proporciona a los autores de la llamada del método un manipulador con el que esperar a que finalice la operación asincrónica. En este caso, el autor de la llamada es el servicio web. Task<ActionResult>
representa el trabajo continuo con un resultado de ActionResult.
GetGizmosAsync
).Dentro del cuerpo del método GetGizmosAsync
se llama a otro método asincrónico, GetGizmosAsync
. GetGizmosAsync
devuelve inmediatamente una instancia de Task<List<Gizmo>>
que finalizará eventualmente cuando los datos estén disponibles. Como no quiere hacer nada más hasta que tenga los datos de gizmo, el código espera la tarea (mediante la palabra clave await). Solo puede usar la palabra clave await en los métodos anotados con la palabra clave async.
La palabra clave await no ocupa el subproceso hasta que se complete la tarea. Registra el resto del método como una devolución de llamada en la tarea y devuelve inmediatamente. Cuando la tarea en espera se complete, invocará esa devolución de llamada y, por tanto, reanudará la ejecución del método justo donde haya parado. Para más información sobre el uso de las palabras clave await y async, y el espacio de nombres Task, vea las referencias asincrónicas.
El siguiente código muestra los métodos GetGizmos
y GetGizmosAsync
.
public List<Gizmo> GetGizmos()
{
var uri = Util.getServiceUri("Gizmos");
using (WebClient webClient = new WebClient())
{
return JsonConvert.DeserializeObject<List<Gizmo>>(
webClient.DownloadString(uri)
);
}
}
public async Task<List<Gizmo>> GetGizmosAsync()
{
var uri = Util.getServiceUri("Gizmos");
using (HttpClient httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(uri);
return (await response.Content.ReadAsAsync<List<Gizmo>>());
}
}
Los cambios asincrónicos son similares a los realizados anteriormente en GizmosAsync.
Task<List<Gizmo>>
y se ha anexado Async al nombre del método.En la imagen siguiente se muestra la vista asincrónica de gizmo.
La presentación en los exploradores de los datos de gizmos es idéntica a la vista creada por la llamada sincrónica. La única diferencia es que la versión asincrónica puede ser más eficaz en cargas pesadas.
Los métodos de acción asincrónicos tienen una ventaja significativa sobre los métodos sincrónicos cuando una acción debe realizar varias operaciones independientes. En el ejemplo proporcionado, el método sincrónico PWG
(para Productos, Widgets y Gizmos) muestra los resultados de tres llamadas de servicio web para obtener una lista de productos, widgets y gizmos. El proyecto deAPI web de ASP.NET que proporciona estos servicios usa Task.Delay para simular la latencia o llamadas de red lentas. Cuando el retraso se establece en 500 milisegundos, el método PWGasync
asincrónico tarda poco más de 500 milisegundos en completarse mientras que la versión PWG
sincrónica tarda más de 1500 milisegundos. El método PWG
sincrónico se muestra en el código siguiente.
public ActionResult PWG()
{
ViewBag.SyncType = "Synchronous";
var widgetService = new WidgetService();
var prodService = new ProductService();
var gizmoService = new GizmoService();
var pwgVM = new ProdGizWidgetVM(
widgetService.GetWidgets(),
prodService.GetProducts(),
gizmoService.GetGizmos()
);
return View("PWG", pwgVM);
}
El método PWGasync
asincrónico se muestra en el código siguiente.
public async Task<ActionResult> PWGasync()
{
ViewBag.SyncType = "Asynchronous";
var widgetService = new WidgetService();
var prodService = new ProductService();
var gizmoService = new GizmoService();
var widgetTask = widgetService.GetWidgetsAsync();
var prodTask = prodService.GetProductsAsync();
var gizmoTask = gizmoService.GetGizmosAsync();
await Task.WhenAll(widgetTask, prodTask, gizmoTask);
var pwgVM = new ProdGizWidgetVM(
widgetTask.Result,
prodTask.Result,
gizmoTask.Result
);
return View("PWG", pwgVM);
}
En la imagen siguiente se muestra la vista devuelta desde el método PWGasync.
Los métodos de acción asincrónicos que devuelven Task<ActionResult>
son cancelables, es decir, toman un parámetro CancellationToken cuando se proporciona uno con el atributo AsyncTimeout. En el código siguiente se muestra el método GizmosCancelAsync
con un tiempo de espera de 150 milisegundos.
[AsyncTimeout(150)]
[HandleError(ExceptionType = typeof(TimeoutException),
View = "TimeoutError")]
public async Task<ActionResult> GizmosCancelAsync(
CancellationToken cancellationToken )
{
ViewBag.SyncOrAsync = "Asynchronous";
var gizmoService = new GizmoService();
return View("Gizmos",
await gizmoService.GetGizmosAsync(cancellationToken));
}
En el código siguiente se muestra la sobrecarga GetGizmosAsync, que toma un parámetro CancellationToken.
public async Task<List<Gizmo>> GetGizmosAsync(string uri,
CancellationToken cancelToken = default(CancellationToken))
{
using (HttpClient httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(uri, cancelToken);
return (await response.Content.ReadAsAsync<List<Gizmo>>());
}
}
En la aplicación de ejemplo proporcionada, al seleccionar el vínculo Demostración del token de cancelación se llama al método GizmosCancelAsync
y se muestra la cancelación de la llamada asincrónica.
Para apreciar los beneficios de una aplicación web asincrónica, es posible que tenga que realizar algunos cambios en la configuración predeterminada del servidor. Tenga en cuenta lo siguiente al configurar y realizar la prueba de esfuerzo de la aplicación web asincrónica.
Windows 7, Windows Vista, y todos los sistemas operativos cliente de Windows tienen un máximo de 10 solicitudes simultáneas. Necesitará un sistema operativo Windows Server para ver los beneficios de los métodos asincrónicos con una carga alta.
Registre .NET 4.5 con IIS desde un símbolo del sistema con privilegios elevados:
%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis -i
Ver Herramienta de registro de IIS en ASP.NET (Aspnet_regiis.exe)
Es posible que tenga que aumentar el límite de cola de HTTP.sys del valor predeterminado de 1000 a 5000. Si el valor es demasiado bajo, es posible que vea a HTTP.sys rechazar solicitudes con un estado HTTP 503. Para cambiar el límite de cola de HTTP.sys:
Observe que en las imágenes anteriores .NET Framework aparece como v4.0, aunque en el grupo de aplicaciones se use .NET 4.5. Para comprender esta discrepancia, vea lo siguiente:
Si la aplicación usa servicios web o System.NET para comunicarse con un back-end mediante HTTP, es posible que tenga que aumentar el elemento connectionManagement/maxconnection. En el caso de las aplicaciones ASP.NET, esta característica está limitada por la característica autoConfig a 12 veces la cantidad de CPU. Esto significa que, en un procesador cuádruple, puede tener como máximo 12 * 4 = 48 conexiones simultáneas a un punto de conexión IP. Como esto está vinculado a autoConfig, la manera más fácil de aumentar maxconnection
en una aplicación ASP.NET consiste en establecer System.Net.ServicePointManager.DefaultConnectionLimit mediante programación con el método Application_Start
del archivo global.asax. Vea la descarga de muestra para obtener un ejemplo.
En .NET 4.5, el valor predeterminado de 5000 para MaxConcurrentRequestsPerCPU debería ser correcto.
Eventos
Campeonato mundial de DataViz de Power BI
14 feb, 16 - 31 mar, 16
Con 4 posibilidades de entrar, podrías ganar un paquete de conferencia y convertirlo en el Live Grand Finale en Las Vegas
Saber másCursos
Ruta de aprendizaje
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
Documentación
Uso de Métodos asincrónicos en ASP.NET 4.5
Este tutorial le enseñará los conceptos básicos de la creación de una aplicación asincrónica de ASP.NET Web Forms mediante Visual Studio Express 2012 para Web, que es gratuita...
Tipos de valor devuelto de acción del controlador de la API web de ASP.NET Core
ActionResult frente a IActionResult
Control de excepciones en ASP.NET Web API: ASP.NET 4.x
Describe ASP.NET Web API ejecuta el control de errores y excepciones y proporciona ejemplos de errores y excepciones.