Usar métodos asincrónicos en ASP.NET 4.5Using Asynchronous Methods in ASP.NET 4.5

por Rick Andersonby Rick Anderson

Este tutorial le enseñará los aspectos básicos de la creación de una aplicación de formularios Web Forms ASP.NET asincrónica mediante Visual Studio Express 2012 para web, que es una versión gratuita de Microsoft Visual Studio.This tutorial will teach you the basics of building an asynchronous ASP.NET Web Forms application using Visual Studio Express 2012 for Web, which is a free version of Microsoft Visual Studio. También puede usar Visual Studio 2012.You can also use Visual Studio 2012. En este tutorial se incluyen las secciones siguientes.The following sections are included in this tutorial.

Se proporciona un ejemplo completo para este tutorial enA complete sample is provided for this tutorial at
https://github.com/RickAndMSFT/Async-ASP.NET/ en el sitio de GitHub .https://github.com/RickAndMSFT/Async-ASP.NET/ on the GitHub site.

Las páginas web de ASP.NET 4,5 de la combinación .net 4,5 permiten registrar métodos asincrónicos que devuelven un objeto de tipo Task.ASP.NET 4.5 Web Pages in combination .NET 4.5 enables you to register asynchronous methods that return an object of type Task. El .NET Framework 4 presentó un concepto de programación asincrónica denominado tarea y ASP.net 4,5 admite la tarea.The .NET Framework 4 introduced an asynchronous programming concept referred to as a Task and ASP.NET 4.5 supports Task. Las tareas se representan mediante el tipo de tarea y los tipos relacionados en el espacio de nombres System. Threading. Tasks .Tasks are represented by the Task type and related types in the System.Threading.Tasks namespace. El .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 de tarea sea mucho menos complejo que los enfoques asincrónicos anteriores.The .NET Framework 4.5 builds on this asynchronous support with the await and async keywords that make working with Task objects much less complex than previous asynchronous approaches. La palabra clave Await es una abreviatura sintáctica para indicar que un fragmento de código debe esperar de forma asincrónica en algún otro fragmento de código.The await keyword is syntactical shorthand for indicating that a piece of code should asynchronously wait on some other piece of code. La palabra clave Async representa una sugerencia que se puede usar para marcar métodos como métodos asincrónicos basados en tareas.The async keyword represents a hint that you can use to mark methods as task-based asynchronous methods. La combinación de Await, Asyncy el objeto de tarea hace que sea mucho más fácil escribir código asincrónico en .net 4,5.The combination of await, async, and the Task object makes it much easier for you to write asynchronous code in .NET 4.5. El nuevo modelo de métodos asincrónicos se denomina patrón asincrónico basado en tareas (TAP).The new model for asynchronous methods is called the Task-based Asynchronous Pattern (TAP). En este tutorial se supone que está familiarizado con los programas asincrónicos mediante las palabras clave Await y Async y el espacio de nombres Task .This tutorial assumes you have some familiarity with asynchronous programing using await and async keywords and the Task namespace.

Para obtener más información sobre el uso de las palabras clave Await y Async y el espacio de nombres Task , vea las referencias siguientes.For more information on the using await and async keywords and the Task namespace, see the following references.

Cómo procesa el grupo de subprocesos las solicitudesHow Requests Are Processed by the Thread Pool

En el servidor Web, el .NET Framework mantiene un grupo de subprocesos que se usan para atender las solicitudes de ASP.NET.On the web server, the .NET Framework maintains a pool of threads that are used to service ASP.NET requests. Cuando se recibe una solicitud, se envía un subproceso del grupo para procesarla.When a request arrives, a thread from the pool is dispatched to process that request. Si la solicitud se procesa de forma sincrónica, el subproceso que procesa la solicitud está ocupado mientras se procesa la solicitud y ese subproceso no puede atender a otra solicitud.If the request is processed synchronously, the thread that processes the request is busy while the request is being processed, and that thread cannot service another request.

Esto podría no ser un problema, porque el grupo de subprocesos puede ser lo suficientemente grande como para alojar muchos subprocesos ocupados.This might not be a problem, because the thread pool can be made large enough to accommodate many busy threads. Sin embargo, el número de subprocesos del grupo de subprocesos es limitado (el máximo predeterminado para .NET 4,5 es 5.000).However, the number of threads in the thread pool is limited (the default maximum for .NET 4.5 is 5,000). En aplicaciones de gran tamaño con una gran simultaneidad de solicitudes de ejecución prolongada, todos los subprocesos disponibles podrían estar ocupados.In large applications with high concurrency of long-running requests, all available threads might be busy. Esta condición se conoce como colapso de subprocesos.This condition is known as thread starvation. Cuando se alcanza esta condición, el servidor web pone en cola las solicitudes.When this condition is reached, the web server queues requests. Si la cola de solicitudes se llena, el servidor Web rechazará las solicitudes con un Estado HTTP 503 (servidor demasiado ocupado).If the request queue becomes full, the web server rejects requests with an HTTP 503 status (Server Too Busy). El grupo de subprocesos de CLR tiene limitaciones en las nuevas inyecciones de subprocesos.The CLR thread pool has limitations on new thread injections. Si la simultaneidad es más grande (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 llamadas de back-end con latencia elevada, la velocidad de inserción de subprocesos limitada puede hacer que la aplicación responda muy mal.If concurrency is bursty (that is, your web site can suddenly get a large number of requests) and all available request threads are busy because of backend calls with high latency, the limited thread injection rate can make your application respond very poorly. Además, cada nuevo subproceso agregado al grupo de subprocesos tiene una sobrecarga (por ejemplo, 1 MB de memoria de pila).Additionally, each new thread added to the thread pool has overhead (such as 1 MB of stack memory). Una aplicación web que usa métodos sincrónicos para atender las llamadas de latencia alta en 4,5 las que el grupo de subprocesos crece hasta el máximo predeterminado de 5, 000 subprocesos consumen aproximadamente 5 GB de memoria más que una aplicación capaz de atender las mismas solicitudes mediante métodos asincrónicos y solo los subprocesos de 50.A web application using synchronous methods to service high latency calls where the thread pool grows to the .NET 4.5 default maximum of 5, 000 threads would consume approximately 5 GB more memory than an application able the service the same requests using asynchronous methods and only 50 threads. Cuando está realizando el trabajo asincrónico, no siempre se usa un subproceso.When you're doing asynchronous work, you're not always using a thread. Por ejemplo, al realizar una solicitud de servicio Web asincrónica, ASP.NET no usará ningún subproceso entre la llamada al método asincrónico y el Await.For example, when you make an asynchronous web service request, ASP.NET will not be using any threads between the async method call and the await. El uso del grupo de subprocesos para atender las solicitudes con latencia alta puede conducir a una gran cantidad de memoria y un uso deficiente del hardware del servidor.Using the thread pool to service requests with high latency can lead to a large memory footprint and poor utilization of the server hardware.

Procesar solicitudes asincrónicasProcessing Asynchronous Requests

En las aplicaciones web que ven un gran número de solicitudes simultáneas en el inicio o que tienen una carga elevada (donde la simultaneidad aumenta repentinamente), realizar llamadas asincrónicas a servicios web aumentará la capacidad de respuesta de la aplicación.In web applications that see a large number of concurrent requests at start-up or has a bursty load (where concurrency increases suddenly), making web service calls asynchronous will increase the responsiveness of your application. Una solicitud asincrónica tarda el mismo tiempo en procesarse que una sincrónica.An asynchronous request takes the same amount of time to process as a synchronous request. Por ejemplo, si una solicitud realiza una llamada de servicio Web que requiere dos segundos para completarse, la solicitud tarda dos segundos si se realiza de forma sincrónica o asincrónica.For example, if a request makes a web service call that requires two seconds to complete, the request takes two seconds whether it is performed synchronously or asynchronously. Sin embargo, durante una llamada asincrónica, no se impide que un subproceso responda a otras solicitudes mientras espera a que se complete la primera solicitud.However, during an asynchronous call, a thread is not blocked from responding to other requests while it waits for the first request to complete. Por consiguiente, las solicitudes asincrónicas impiden la puesta en cola de solicitudes y el crecimiento del grupo de subprocesos cuando hay muchas solicitudes simultáneas que invocan operaciones de ejecución prolongada.Therefore, asynchronous requests prevent request queuing and thread pool growth when there are many concurrent requests that invoke long-running operations.

Elegir métodos sincrónicos o asincrónicosChoosing Synchronous or Asynchronous Methods

En esta sección se enumeran las directrices sobre Cuándo usar métodos sincrónicos o asincrónicos.This section lists guidelines for when to use synchronous or asynchronous Methods. Estas son simplemente instrucciones; examine cada aplicación individualmente para determinar si los métodos asincrónicos ayudan a mejorar el rendimiento.These are just guidelines; examine each application individually to determine whether asynchronous methods help with performance.

En general, use métodos sincrónicos para las siguientes condiciones:In general, use synchronous methods for the following conditions:

  • Las operaciones son simples o de ejecución breve.The operations are simple or short-running.
  • La simplicidad es más importante que la eficacia.Simplicity is more important than efficiency.
  • Las operaciones son principalmente operaciones de la CPU y no operaciones que requieren una gran sobrecarga del disco o de la red.The operations are primarily CPU operations instead of operations that involve extensive disk or network overhead. El uso de métodos asincrónicos en operaciones enlazadas a la CPU no proporciona ninguna ventaja y produce una mayor sobrecarga.Using asynchronous methods on CPU-bound operations provides no benefits and results in more overhead.

En general, use métodos asincrónicos para las siguientes condiciones:In general, use asynchronous methods for the following conditions:

  • Está llamando a servicios que se pueden consumir mediante métodos asincrónicos y usa .NET 4,5 o superior.You're calling services that can be consumed through asynchronous methods, and you're using .NET 4.5 or higher.

  • Las operaciones están relacionadas con la red o con E/S y no con la CPU.The operations are network-bound or I/O-bound instead of CPU-bound.

  • El paralelismo es más importante que la simplicidad de código.Parallelism is more important than simplicity of code.

  • Se desea proporcionar un mecanismo que permita al usuario cancelar solicitudes de ejecución prolongada.You want to provide a mechanism that lets users cancel a long-running request.

  • Cuando la ventaja de cambiar subprocesos supera el costo del cambio de contexto.When the benefit of switching threads outweighs the cost of the context switch. En general, debe hacer que un método sea asincrónico si el método sincrónico bloquea el subproceso de solicitud ASP.NET mientras no realiza ningún trabajo.In general, you should make a method asynchronous if the synchronous method blocks the ASP.NET request thread while doing no work. Al hacer que la llamada sea asincrónica, el subproceso de solicitud ASP.NET no se bloquea sin ningún trabajo mientras espera a que se complete la solicitud de servicio Web.By making the call asynchronous, the ASP.NET request thread is not blocked doing no work while it waits for the web service request to complete.

  • Las pruebas muestran que las operaciones de bloqueo son un cuello de botella en el rendimiento del sitio y que IIS puede atender más solicitudes mediante métodos asincrónicos para estas llamadas de bloqueo.Testing shows that the blocking operations are a bottleneck in site performance and that IIS can service more requests by using asynchronous methods for these blocking calls.

    En el ejemplo descargable se muestra cómo usar los métodos asincrónicos de forma eficaz.The downloadable sample shows how to use asynchronous methods effectively. El ejemplo proporcionado se diseñó para proporcionar una demostración sencilla de la programación asincrónica en ASP.NET 4,5.The sample provided was designed to provide a simple demonstration of asynchronous programming in ASP.NET 4.5. El ejemplo no pretende ser una arquitectura de referencia para la programación asincrónica en ASP.NET.The sample is not intended to be a reference architecture for asynchronous programming in ASP.NET. El programa de ejemplo llama a los métodos de ASP.net web API que, a su vez, llaman a Task. Delay para simular llamadas a servicios Web de ejecución prolongada.The sample program calls ASP.NET Web API methods which in turn call Task.Delay to simulate long-running web service calls. La mayoría de las aplicaciones de producción no mostrarán tales ventajas obvias en el uso de métodos asincrónicos.Most production applications will not show such obvious benefits to using asynchronous Methods.

Pocas aplicaciones requieren que todos los métodos sean asincrónicos.Few applications require all methods to be asynchronous. A menudo, convertir algunos métodos sincrónicos en métodos asincrónicos proporciona el mejor aumento de la eficacia para la cantidad de trabajo necesario.Often, converting a few synchronous methods to asynchronous methods provides the best efficiency increase for the amount of work required.

La aplicación de ejemploThe Sample Application

Puede descargar la aplicación de ejemplo desde https://github.com/RickAndMSFT/Async-ASP.NET en el sitio de GitHub .You can download the sample application from https://github.com/RickAndMSFT/Async-ASP.NET on the GitHub site. El repositorio consta de tres proyectos:The repository consists of three projects:

  • WebAppAsync: el proyecto de formularios web forms de ASP.net que usa el servicio WEBAPIPWG de la API Web.WebAppAsync: The ASP.NET Web Forms project that consumes the Web API WebAPIpwg service. La mayor parte del código de este tutorial procede de este proyecto.Most of the code for this tutorial is from the this project.
  • WebAPIpgw: el proyecto de API Web de ASP.NET MVC 4 que implementa los Products, Gizmos and Widgets controladores.WebAPIpgw: The ASP.NET MVC 4 Web API project that implements the Products, Gizmos and Widgets controllers. Proporciona los datos para el proyecto WebAppAsync y el proyecto Mvc4Async .It provides the data for the WebAppAsync project and the Mvc4Async project.
  • Mvc4Async: el proyecto ASP.NET MVC 4 que contiene el código usado en otro tutorial.Mvc4Async: The ASP.NET MVC 4 project that contains the code used in another tutorial. Realiza llamadas API Web al servicio WebAPIpwg .It makes Web API calls to the WebAPIpwg service.

Página sincrónica de GizmosThe Gizmos Synchronous Page

En el código siguiente se muestra el Page_Load método sincrónico que se usa para mostrar una lista de Gizmos.The following code shows the Page_Load synchronous method that is used to display a list of gizmos. (En este artículo, un Gizmo es un dispositivo mecánico ficticio).(For this article, a gizmo is a fictional mechanical device.)

public partial class Gizmos : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        var gizmoService = new GizmoService();
        GizmoGridView.DataSource = gizmoService.GetGizmos();
        GizmoGridView.DataBind();
    }
}

En el código siguiente se muestra el GetGizmos método del servicio Gizmo.The following code shows the GetGizmos method of the gizmo service.

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 GizmoService GetGizmos método pasa un URI a un ASP.net web API servicio http que devuelve una lista de datos de Gizmos.The GizmoService GetGizmos method passes a URI to an ASP.NET Web API HTTP service which returns a list of gizmos data. El proyecto WebAPIpgw contiene la implementación de la API Web gizmos, widget y los product controladores.The WebAPIpgw project contains the implementation of the Web API gizmos, widget and product controllers.
En la imagen siguiente se muestra la página Gizmos del proyecto de ejemplo.The following image shows the gizmos page from the sample project.

Gizmos

Crear una página Gizmos asincrónicaCreating an Asynchronous Gizmos Page

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 complejas transformaciones necesarias para la programación asincrónica.The sample uses the new async and await keywords (available in .NET 4.5 and Visual Studio 2012) to let the compiler be responsible for maintaining the complicated transformations necessary for asynchronous programming. El compilador permite escribir código mediante las construcciones de flujo de control sincrónicos de C# y el compilador aplica automáticamente las transformaciones necesarias para utilizar las devoluciones de llamada con el fin de evitar el bloqueo de subprocesos.The compiler lets you write code using the C#'s synchronous control flow constructs and the compiler automatically applies the transformations necessary to use callbacks in order to avoid blocking threads.

Las páginas asincrónicas de ASP.NET deben incluir la Directiva de Página con el Async atributo establecido en "true".ASP.NET asynchronous pages must include the Page directive with the Async attribute set to "true". En el código siguiente se muestra la directiva Page con el Async atributo establecido en "true" para la página GizmosAsync. aspx .The following code shows the Page directive with the Async attribute set to "true" for the GizmosAsync.aspx page.

<%@ Page Async="true"  Language="C#" AutoEventWireup="true" 
    CodeBehind="GizmosAsync.aspx.cs" Inherits="WebAppAsync.GizmosAsync" %>

En el código siguiente se muestra el Gizmos Page_Load método sincrónico y la GizmosAsync Página asincrónica.The following code shows the Gizmos synchronous Page_Load method and the GizmosAsync asynchronous page. Si el explorador admite el elemento de < marca > HTML 5, verá los cambios en GizmosAsync en amarillo resaltado.If your browser supports the HTML 5 <mark> element, you'll see the changes in GizmosAsync in yellow highlight.

protected void Page_Load(object sender, EventArgs e)
{
   var gizmoService = new GizmoService();
   GizmoGridView.DataSource = gizmoService.GetGizmos();
   GizmoGridView.DataBind();
}

La versión asincrónica:The asynchronous version:

protected void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(GetGizmosSvcAsync));
}

private async Task GetGizmosSvcAsync()
{
    var gizmoService = new GizmoService();
    GizmosGridView.DataSource = await gizmoService.GetGizmosAsync();
    GizmosGridView.DataBind();
}

Se aplicaron los siguientes cambios para permitir que la GizmosAsync página sea asincrónica.The following changes were applied to allow the GizmosAsync page be asynchronous.

  • La directiva Page debe tener el Async atributo establecido en "true".The Page directive must have the Async attribute set to "true".
  • El RegisterAsyncTask método se usa para registrar una tarea asincrónica que contiene el código que se ejecuta de forma asincrónica.The RegisterAsyncTask method is used to register an asynchronous task containing the code which runs asynchronously.
  • El nuevo GetGizmosSvcAsync método se marca con la palabra clave Async , que indica al compilador que genere devoluciones de llamada para partes del cuerpo y que cree automáticamente un Task que se devuelva.The new GetGizmosSvcAsync method is marked with the async keyword, which tells the compiler to generate callbacks for parts of the body and to automatically create a Task that is returned.
  • "Async " se anexó al nombre del método asincrónico."Async" was appended to the asynchronous method name. Anexar "Async" no es necesario, pero es la Convención al escribir métodos asincrónicos.Appending "Async" is not required but is the convention when writing asynchronous methods.
  • El tipo de valor devuelto del nuevo GetGizmosSvcAsync método es Task .The return type of the new GetGizmosSvcAsync method is Task. El tipo de valor devuelto de Task representa el trabajo en curso y proporciona a los llamadores del método un identificador a través del cual se espera la finalización de la operación asincrónica.The return type of Task represents ongoing work and provides callers of the method with a handle through which to wait for the asynchronous operation's completion.
  • La palabra clave Await se aplicó a la llamada al servicio Web.The await keyword was applied to the web service call.
  • Se llamó a la API del servicio Web asincrónica ( GetGizmosAsync ).The asynchronous web service API was called (GetGizmosAsync).

Dentro del GetGizmosSvcAsync cuerpo del método otro método asincrónico, GetGizmosAsync se llama a.Inside of the GetGizmosSvcAsync method body another asynchronous method, GetGizmosAsync is called. GetGizmosAsync devuelve inmediatamente un Task<List<Gizmo>> que se completará cuando los datos estén disponibles.GetGizmosAsync immediately returns a Task<List<Gizmo>> that will eventually complete when the data is available. Dado que no desea hacer nada más hasta que tenga los datos de Gizmo, el código espera la tarea (mediante la palabra clave Await ).Because you don't want to do anything else until you have the gizmo data, the code awaits the task (using the await keyword). Solo puede utilizar la palabra clave Await en métodos anotados con la palabra clave Async .You can use the await keyword only in methods annotated with the async keyword.

La palabra clave Await no bloquea el subproceso hasta que se completa la tarea.The await keyword does not block the thread until the task is complete. Registra el resto del método como una devolución de llamada en la tarea y devuelve inmediatamente.It signs up the rest of the method as a callback on the task, and immediately returns. Cuando se complete la tarea esperada, se invocará esa devolución de llamada y, por tanto, se reanudará la ejecución del método justo donde se quedó.When the awaited task eventually completes, it will invoke that callback and thus resume the execution of the method right where it left off. Para obtener más información sobre el uso de las palabras clave Await y Async y el espacio de nombres Task , vea referencias asincrónicas.For more information on using the await and async keywords and the Task namespace, see the async references.

El siguiente código muestra los métodos GetGizmos y GetGizmosAsync.The following code shows the GetGizmos and GetGizmosAsync methods.

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 (WebClient webClient = new WebClient())
    {
        return JsonConvert.DeserializeObject<List<Gizmo>>(
            await webClient.DownloadStringTaskAsync(uri)
        );
    }
}

Los cambios asincrónicos son similares a los que se realizaron en el GizmosAsync anterior.The asynchronous changes are similar to those made to the GizmosAsync above.

  • La firma del método se anotó con la palabra clave Async , el tipo de valor devuelto se cambió a Task<List<Gizmo>> y Async se anexó al nombre del método.The method signature was annotated with the async keyword, the return type was changed to Task<List<Gizmo>>, and Async was appended to the method name.
  • La clase HttpClient asincrónica se usa en lugar de la clase WebClient sincrónica.The asynchronous HttpClient class is used instead of the synchronous WebClient class.
  • La palabra clave Await se aplicó al método asincrónicoGetAsync de HttpClient.The await keyword was applied to the HttpClientGetAsync asynchronous method.

En la imagen siguiente se muestra la vista Gizmo asincrónica.The following image shows the asynchronous gizmo view.

async

La presentación de los exploradores de los datos de Gizmos es idéntica a la vista creada por la llamada sincrónica.The browsers presentation of the gizmos data is identical to the view created by the synchronous call. La única diferencia es que la versión asincrónica puede ser más eficaz en cargas pesadas.The only difference is the asynchronous version may be more performant under heavy loads.

Notas de RegisterAsyncTaskRegisterAsyncTask Notes

Los métodos enlazados con RegisterAsyncTask se ejecutarán inmediatamente después de la representaciónprevia.Methods hooked up with RegisterAsyncTask will run immediately after PreRender.

Si usa eventos de página de void void directamente, como se muestra en el código siguiente:If you use async void page events directly, as shown in the following code:

protected async void Page_Load(object sender, EventArgs e) {
    await ...;
    // do work
}

ya no tiene control total sobre cuándo se ejecutan los eventos.you no longer have full control over when events execute. Por ejemplo, si es. aspx y. Los eventos de definición maestra Page_Load y uno o ambos son asíncronos, por lo que no se puede garantizar el orden de ejecución.For example, if both an .aspx and a .Master define Page_Load events and one or both of them are asynchronous, the order of execution can't be guaranteed. Se aplica el mismo orden indeterminado para los controladores de eventos (como async void Button_Click ).The same indeterminate order for event handlers (such as async void Button_Click ) applies.

Realizar varias operaciones en paraleloPerforming Multiple Operations in Parallel

Los métodos asincrónicos tienen una ventaja significativa con respecto a los métodos sincrónicos cuando una acción debe realizar varias operaciones independientes.Asynchronous Methods have a significant advantage over synchronous methods when an action must perform several independent operations. En el ejemplo proporcionado, la página sincrónica PWG. aspx(para productos, widgets y Gizmos) muestra los resultados de tres llamadas al servicio web para obtener una lista de productos, widgets y Gizmos.In the sample provided, the synchronous page PWG.aspx(for Products, Widgets and Gizmos) displays the results of three web service calls to get a list of products, widgets, and gizmos. El proyecto de ASP.net web API que proporciona estos servicios usa Task. Delay para simular latencia o llamadas de red lentas.The ASP.NET Web API project that provides these services uses Task.Delay to simulate latency or slow network calls. Cuando el retraso se establece en 500 milisegundos, la página PWGasync. aspx asincrónica tarda un poco más de 500 milisegundos en completarse, mientras que la PWG versión sincrónica tarda más de 1.500 milisegundos.When the delay is set to 500 milliseconds, the asynchronous PWGasync.aspx page takes a little over 500 milliseconds to complete while the synchronous PWG version takes over 1,500 milliseconds. En el código siguiente se muestra la página sincrónicas de PWG. aspx .The synchronous PWG.aspx page is shown in the following code.

protected void Page_Load(object sender, EventArgs e)
{
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    var widgetService = new WidgetService();
    var prodService = new ProductService();
    var gizmoService = new GizmoService();

    var pwgVM = new ProdGizWidgetVM(
        widgetService.GetWidgets(),
        prodService.GetProducts(),
        gizmoService.GetGizmos()
       );
    WidgetGridView.DataSource = pwgVM.widgetList;
    WidgetGridView.DataBind();
    ProductGridView.DataSource = pwgVM.prodList;
    ProductGridView.DataBind();
    GizmoGridView.DataSource = pwgVM.gizmoList;
    GizmoGridView.DataBind();

    stopWatch.Stop();
    ElapsedTimeLabel.Text = String.Format("Elapsed time: {0}", 
        stopWatch.Elapsed.Milliseconds / 1000.0);
}

PWGasyncA continuación se muestra el código asincrónico subyacente.The asynchronous PWGasync code behind is shown below.

protected void Page_Load(object sender, EventArgs e)
{
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();
    RegisterAsyncTask(new PageAsyncTask(GetPWGsrvAsync));
    stopWatch.Stop();
    ElapsedTimeLabel.Text = String.Format("Elapsed time: {0}",
        stopWatch.Elapsed.Milliseconds / 1000.0);
}

private async Task GetPWGsrvAsync()
{
    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
       );

    WidgetGridView.DataSource = pwgVM.widgetList;
    WidgetGridView.DataBind();
    ProductGridView.DataSource = pwgVM.prodList;
    ProductGridView.DataBind();
    GizmoGridView.DataSource = pwgVM.gizmoList;
    GizmoGridView.DataBind();           
}

En la imagen siguiente se muestra la vista devuelta desde la página asincrónica PWGasync. aspx .The following image shows the view returned from the asynchronous PWGasync.aspx page.

Usar un token de cancelaciónUsing a Cancellation Token

Los métodos asincrónicos que devuelven Task se pueden cancelar, es decir, toman un parámetro CancellationToken cuando se proporciona uno con el AsyncTimeout atributo de la directiva Page .Asynchronous Methods returning Taskare cancelable, that is they take a CancellationToken parameter when one is provided with the AsyncTimeout attribute of the Page directive. En el código siguiente se muestra la página GizmosCancelAsync. aspx con un tiempo de espera de en el segundo.The following code shows the GizmosCancelAsync.aspx page with a timeout of on second.

<%@ Page  Async="true"  AsyncTimeout="1" 
    Language="C#" AutoEventWireup="true" 
    CodeBehind="GizmosCancelAsync.aspx.cs" 
    Inherits="WebAppAsync.GizmosCancelAsync" %>

En el código siguiente se muestra el archivo GizmosCancelAsync.aspx.CS .The following code shows the GizmosCancelAsync.aspx.cs file.

protected void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(GetGizmosSvcCancelAsync));
}

private async Task GetGizmosSvcCancelAsync(CancellationToken cancellationToken)
{
    var gizmoService = new GizmoService();
    var gizmoList = await gizmoService.GetGizmosAsync(cancellationToken);
    GizmosGridView.DataSource = gizmoList;
    GizmosGridView.DataBind();
}
private void Page_Error(object sender, EventArgs e)
{
    Exception exc = Server.GetLastError();

    if (exc is TimeoutException)
    {
        // Pass the error on to the Timeout Error page
        Server.Transfer("TimeoutErrorPage.aspx", true);
    }
}

En la aplicación de ejemplo proporcionada, al seleccionar el vínculo GizmosCancelAsync se llama a la página GizmosCancelAsync. aspx y se muestra la cancelación (agotando el tiempo de espera) de la llamada asincrónica.In the sample application provided, selecting the GizmosCancelAsync link calls the GizmosCancelAsync.aspx page and demonstrates the cancellation (by timing out) of the asynchronous call. Dado que el tiempo de retraso está dentro de un intervalo aleatorio, puede que tenga que actualizar la página un par de veces para obtener el mensaje de error de tiempo de espera.Because the delay time is within a random range, you might need to refresh the page a couple times to get the time out error message.

Configuración del servidor para las llamadas de servicio Web de alta simultaneidad y latencia altaServer Configuration for High Concurrency/High Latency Web Service Calls

Para obtener las ventajas de una aplicación web asincrónica, es posible que tenga que realizar algunos cambios en la configuración predeterminada del servidor.To realize the benefits of an asynchronous web application, you might need to make some changes to the default server configuration. Tenga en cuenta lo siguiente al configurar y realizar pruebas de esfuerzo de la aplicación web asincrónica.Keep the following in mind when configuring and stress testing your asynchronous web application.

  • Windows 7, Windows Vista, Window 8 y todos los sistemas operativos de cliente de Windows tienen un máximo de 10 solicitudes simultáneas.Windows 7, Windows Vista, Window 8, and all Windows client operating systems have a maximum of 10 concurrent requests. Necesitará un sistema operativo Windows Server para ver las ventajas de los métodos asincrónicos con una carga elevada.You'll need a Windows Server operating system to see the benefits of asynchronous methods under high load.

  • Registre .NET 4,5 con IIS desde un símbolo del sistema con privilegios elevados mediante el comando siguiente:Register .NET 4.5 with IIS from an elevated command prompt using the following command:
    %windir%\Microsoft.NET\Framework64 \v4.0.30319\aspnet _ regiis-i%windir%\Microsoft.NET\Framework64 \v4.0.30319\aspnet_regiis -i
    Consulte ASP.net IIS registration Tool (Aspnet _regiis.exe)See ASP.NET IIS Registration Tool (Aspnet_regiis.exe)

  • Es posible que tenga que aumentar el límite de cola de HTTP.sys del valor predeterminado de 1.000 a 5.000.You might need to increase the HTTP.sys queue limit from the default value of 1,000 to 5,000. Si el valor es demasiado bajo, es posible que vea HTTP.sys rechazar solicitudes con un estado http 503.If the setting is too low, you may see HTTP.sys reject requests with a HTTP 503 status. Para cambiar el límite de cola de HTTP.sys:To change the HTTP.sys queue limit:

    • Abra el administrador de IIS y navegue hasta el panel grupos de aplicaciones.Open IIS manager and navigate to the Application Pools pane.
    • Haga clic con el botón derecho en el grupo de aplicaciones de destino y seleccione Configuración avanzada.Right click on the target application pool and select Advanced Settings.
      financierosadvanced
    • En el cuadro de diálogo Configuración avanzada , cambie la longitud de la cola de 1.000 a 5.000.In the Advanced Settings dialog box, change Queue Length from 1,000 to 5,000.
      Longitud de la colaQueue length

    Tenga en cuenta que en las imágenes anteriores, .NET Framework se muestra como v 4.0, aunque el grupo de aplicaciones use .NET 4,5.Note in the images above, the .NET framework is listed as v4.0, even though the application pool is using .NET 4.5. Para comprender esta discrepancia, consulte lo siguiente:To understand this discrepancy, see the following:

  • Control de versiones de .NET y compatibilidad con múltiples versiones: .NET 4,5 es una actualización local a .NET 4,0.NET Versioning and Multi-Targeting - .NET 4.5 is an in-place upgrade to .NET 4.0

  • Cómo establecer una aplicación de IIS o AppPool para usar ASP.NET 3,5 en lugar de 2,0How to set an IIS Application or AppPool to use ASP.NET 3.5 rather than 2.0

  • Versiones y dependencias de .NET Framework.NET Framework Versions and Dependencies

  • Si su aplicación usa servicios web o System.NET para comunicarse con un back-end a través de HTTP, puede que tenga que aumentar el elemento connectionManagement/MaxConnection .If your application is using web services or System.NET to communicate with a backend over HTTP you may need to increase the connectionManagement/maxconnection element. En el caso de las aplicaciones ASP.NET, está limitado por la característica AutoConfig a 12 veces el número de CPU.For ASP.NET applications, this is limited by the autoConfig feature to 12 times the number of CPUs. Esto significa que en un proceso cuádruple, puede tener como máximo 12 * 4 = 48 conexiones simultáneas a un punto de conexión de IP.That means that on a quad-proc, you can have at most 12 * 4 = 48 concurrent connections to an IP end point. Dado que está vinculado a AutoConfig, la manera más fácil de aumentar maxconnection en una aplicación ASP.net es establecer System .net. ServicePointManager. DefaultConnectionLimit mediante programación en el Application_Start método from del archivo global. asax .Because this is tied to autoConfig, the easiest way to increase maxconnection in an ASP.NET application is to set System.Net.ServicePointManager.DefaultConnectionLimit programmatically in the from Application_Start method in the global.asax file. Vea la descarga de ejemplo para obtener un ejemplo.See the sample download for an example.

  • En .NET 4,5, el valor predeterminado de 5000 para MaxConcurrentRequestsPerCPU debe ser correcto.In .NET 4.5, the default of 5000 for MaxConcurrentRequestsPerCPU should be fine.

ColaboradoresContributors