Llamar a API asincrónicas en C# o Visual Basic

La Plataforma universal de Windows (UWP) incluye muchas API asincrónicas para que la aplicación tenga capacidad de respuesta mientras realiza trabajos que puedan llevar algún tiempo. En este tema se describe cómo usar métodos asincrónicos desde la UWP en C# o Microsoft Visual Basic.

Las API asincrónicas impiden que la aplicación espere a que se completen operaciones grandes antes de continuar la ejecución. Por ejemplo, una aplicación que descarga información de Internet puede pasar varios segundos esperando a que llegue la información. Si usas un método sincrónico para recuperar la información, la aplicación se bloquea hasta que el método vuelva. La aplicación no responderá a la interacción del usuario y, dado que parece que no responde, el usuario podría frustrarse. Al proporcionar API asincrónicas, la UWP ayuda a asegurarse de que la aplicación sigue respondiendo al usuario cuando realiza operaciones largas.

La mayoría de las API asincrónicas de UWP no tienen homólogos sincrónicos, por lo que debes asegurarte de saber cómo usar las API asincrónicas con C# o Visual Basic en tu aplicación de Plataforma universal de Windows (UWP). Aquí se muestra cómo llamar a las API asincrónicas de la UWP.

Uso de API asincrónicas

Por convención, a los métodos asincrónicos se les asignan nombres que terminan en "Async". Normalmente, se llama a api asincrónicas en respuesta a la acción de un usuario, como cuando el usuario hace clic en un botón. Llamar a un método asincrónico en un controlador de eventos es una de las formas más sencillas de usar API asincrónicas. Aquí usamos el operador await como ejemplo.

Supongamos que tiene una aplicación que muestra los títulos de las entradas de blog de una ubicación determinada. La aplicación tiene un botón en el que el usuario hace clic para obtener los títulos. Los títulos se muestran en un TextBlock. Cuando el usuario hace clic en el botón, es importante que la aplicación siga respondiendo mientras espera la información del sitio web del blog. Para garantizar esta capacidad de respuesta, la UWP proporciona un método asincrónico, SyndicationClient.RetrieveFeedAsync, para descargar la fuente.

En este ejemplo se obtienen las listas de entradas de blog de un blog llamando al método asincrónico SyndicationClient.RetrieveFeedAsync y esperando el resultado.

// Put the keyword async on the declaration of the event handler.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{

    Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();

    Uri feedUri
        = new Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");

    try
    {
        SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

        // The rest of this method executes after await RetrieveFeedAsync completes.
        rssOutput.Text = feed.Title.Text + Environment.NewLine;

        foreach (SyndicationItem item in feed.Items)
        {
            rssOutput.Text += item.Title.Text + ", " +
                             item.PublishedDate.ToString() + Environment.NewLine;
        }
    }
    catch (Exception ex)
    {
        // Log Error.
        rssOutput.Text =
            "I'm sorry, but I couldn't load the page," +
            " possibly due to network problems." +
            "Here's the error message I received: "
            + ex.ToString();
    }
}
' Put the keyword Async on the declaration of the event handler.
Private Async Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
    Dim client As New Windows.Web.Syndication.SyndicationClient()
    Dim feedUri As New Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx")

    Try
        Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(feedUri)

        ' The rest of this method executes after the await operation completes.
        rssOutput.Text = feed.Title.Text & vbCrLf

        For Each item In feed.Items
            rssOutput.Text += $"{item.Title.Text}, {item.PublishedDate.ToString()}{vbCrLf}"
        Next

    Catch ex As Exception
        ' Log Error.
        rssOutput.Text = "I'm sorry, but I couldn't load the page," &
                         " possibly due to network problems." &
                         "Here's the error message I received: " &
                          ex.ToString()
    End Try

End Sub

Hay un par de cosas importantes sobre este ejemplo. En primer lugar, SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) la línea usa el operador await con la llamada al método asincrónico RetrieveFeedAsync. Puede pensar en el operador await como indicar al compilador que está llamando a un método asincrónico, lo que hace que el compilador realice algún trabajo adicional para que no tenga que hacerlo. A continuación, la declaración del controlador de eventos incluye la palabra clave async. Debe incluir esta palabra clave en la declaración de método de cualquier método en el que use el operador await .

En este tema, no veremos muchos detalles de lo que hace el compilador con el operador await , pero vamos a examinar lo que hace la aplicación para que sea asincrónico y con capacidad de respuesta. Tenga en cuenta lo que sucede cuando se usa código sincrónico. Por ejemplo, supongamos que hay un método denominado SyndicationClient.RetrieveFeed que es sincrónico. (No hay este método, pero imagine que hay). Si la aplicación incluía la línea SyndicationFeed feed = client.RetrieveFeed(feedUri), en lugar de SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), la ejecución de la aplicación se detendría hasta que el valor devuelto de RetrieveFeed esté disponible. Y mientras la aplicación espera a que se complete el método, no puede responder a ningún otro evento, como otro evento Click. Es decir, la aplicación se bloquearía hasta RetrieveFeed que vuelva.

Pero si llama a client.RetrieveFeedAsync, el método inicia la recuperación y devuelve inmediatamente. Cuando se usa await con RetrieveFeedAsync, la aplicación sale temporalmente del controlador de eventos. A continuación, puede procesar otros eventos mientras RetrieveFeedAsync se ejecuta de forma asincrónica. Esto mantiene la respuesta de la aplicación al usuario. Cuando RetrieveFeedAsync finaliza y SyndicationFeed está disponible, la aplicación básicamente vuelve a escribir el controlador de eventos donde se dejó, después SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri)de y finaliza el resto del método.

Lo bueno de usar el operador await es que el código no tiene un aspecto muy diferente de la apariencia del código si usó el método imaginario RetrieveFeed . Hay maneras de escribir código asincrónico en C# o Visual Basic sin el operador await , pero el código resultante tiende a resaltar la mecánica de la ejecución asincrónica. Esto hace que el código asincrónico sea difícil de escribir, difícil de entender y difícil de mantener. Mediante el operador await , obtendrá las ventajas de una aplicación asincrónica sin que el código sea complejo.

Tipos devueltos y resultados de API asincrónicas

Si ha seguido el vínculo a RetrieveFeedAsync, es posible que haya observado que el tipo de valor devuelto de RetrieveFeedAsync no es syndicationFeed. En su lugar, el tipo de valor devuelto es IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>. Visto desde la sintaxis sin procesar, una API asincrónica devuelve un objeto que contiene el resultado dentro de ella. Aunque es común, y a veces resulta útil, pensar en un método asincrónico como esperable, el operador await funciona realmente en el valor devuelto del método, no en el método . Cuando se aplica el operador await , lo que se devuelve es el resultado de llamar a GetResult en el objeto devuelto por el método . En el ejemplo, SyndicationFeed es el resultado de RetrieveFeedAsync.GetResult().

Al usar un método asincrónico, puede examinar la firma para ver lo que obtendrá después de esperar el valor devuelto por el método . Todas las API asincrónicas de la UWP devuelven uno de los siguientes tipos:

El tipo de resultado de un método asincrónico es el mismo que el TResult parámetro de tipo. Los tipos sin un TResult no tienen un resultado. Puede considerar que el resultado es nulo. En Visual Basic, un procedimiento Sub es equivalente a un método con un tipo de valor devuelto void .

En la tabla siguiente se proporcionan ejemplos de métodos asincrónicos y se enumeran el tipo de valor devuelto y el tipo de resultado de cada uno.

Método asincrónico Tipo de valor devuelto Tipo de resultado
SyndicationClient.RetrieveFeedAsync IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> SyndicationFeed
FileOpenPicker.PickSingleFileAsync IAsyncOperation<StorageFile> StorageFile
XmlDocument.SaveToFileAsync IAsyncAction void
InkStrokeContainer.LoadAsync IAsyncActionWithProgress<UInt64> void
DataReader.LoadAsync DataReaderLoadOperation, una clase de resultados personalizada que implementa IAsyncOperation<UInt32> UInt32

 

Los métodos asincrónicos definidos en .NET para aplicaciones para UWP tienen el tipo de valor devuelto Task o Task<TResult>. Los métodos que devuelven Task son similares a los métodos asincrónicos de UWP que devuelven IAsyncAction. En cada caso, el resultado del método asincrónico es void. El tipo de valor devuelto Task<TResult> es similar a IAsyncOperation<TResult> en que el resultado del método asincrónico al ejecutar la tarea es el mismo tipo que el TResult parámetro type. Para obtener más información sobre el uso de .NET para aplicaciones y tareas para UWP, consulta Introducción a .NET para aplicaciones de Windows Runtime.

Control de errores

Cuando se usa el operador await para recuperar los resultados de un método asincrónico, puede usar un bloque try/catch para controlar los errores que se producen en métodos asincrónicos, igual que para los métodos sincrónicos. En el ejemplo anterior se ajusta el método RetrieveFeedAsync y la operación await en un bloque try/catch para controlar los errores cuando se produce una excepción.

Cuando los métodos asincrónicos llaman a otros métodos asincrónicos, cualquier método asincrónico que produzca una excepción se propagará a los métodos externos. Esto significa que puede colocar un bloque try/catch en el método más externo para detectar errores para los métodos asincrónicos anidados. De nuevo, esto es similar a cómo se detectan excepciones para métodos sincrónicos. Sin embargo, no puede usar await en el bloque catch.

Sugerencia A partir de C# en Microsoft Visual Studio 2005, puede usar await en el bloque catch .

Resumen y pasos siguientes

El patrón de llamar a un método asincrónico que se muestra aquí es el más sencillo de usar al llamar a las API asincrónicas en un controlador de eventos. También puede usar este patrón al llamar a un método asincrónico en un método invalidado que devuelva void o un Sub en Visual Basic.

A medida que encuentres métodos asincrónicos en UWP, es importante recordar:

  • Por convención, a los métodos asincrónicos se les asignan nombres que terminan en "Async".
  • Cualquier método que use el operador await debe tener su declaración marcada con la palabra clave async .
  • Cuando una aplicación encuentra el operador await , la aplicación sigue respondiendo a la interacción del usuario mientras se ejecuta el método asincrónico.
  • Esperando el valor devuelto por un método asincrónico devuelve un objeto que contiene el resultado. En la mayoría de los casos, el resultado contenido en el valor devuelto es lo que resulta útil, no el propio valor devuelto. Puede encontrar el tipo del valor contenido dentro del resultado examinando el tipo de valor devuelto del método asincrónico.
  • El uso de API asincrónicas y patrones asincrónicos suele ser una manera de mejorar la capacidad de respuesta de la aplicación.

En el ejemplo de este tema se genera texto similar al siguiente.

Windows Experience Blog
PC Snapshot: Sony VAIO Y, 8/9/2011 10:26:56 AM -07:00
Tech Tuesday Live Twitter #Chat: Too Much Tech #win7tech, 8/8/2011 12:48:26 PM -07:00
Windows 7 themes: what’s new and what’s popular!, 8/4/2011 11:56:28 AM -07:00
PC Snapshot: Toshiba Satellite A665 3D, 8/2/2011 8:59:15 AM -07:00
Time for new school supplies? Find back-to-school deals on Windows 7 PCs and Office 2010, 8/1/2011 2:14:40 PM -07:00
Best PCs for blogging (or working) on the go, 8/1/2011 10:08:14 AM -07:00
Tech Tuesday – Blogging Tips and Tricks–#win7tech, 8/1/2011 9:35:54 AM -07:00
PC Snapshot: Lenovo IdeaPad U460, 7/29/2011 9:23:05 AM -07:00
GIVEAWAY: Survive BlogHer with a Sony VAIO SA and a Samsung Focus, 7/28/2011 7:27:14 AM -07:00
3 Ways to Stay Cool This Summer, 7/26/2011 4:58:23 PM -07:00
Getting RAW support in Photo Gallery & Windows 7 (…and a contest!), 7/26/2011 10:40:51 AM -07:00
Tech Tuesdays Live Twitter Chats: Photography Tips, Tricks and Essentials, 7/25/2011 12:33:06 PM -07:00
3 Tips to Go Green With Your PC, 7/22/2011 9:19:43 AM -07:00
How to: Buy a Green PC, 7/22/2011 9:13:22 AM -07:00
Windows 7 themes: the distinctive artwork of Cheng Ling, 7/20/2011 9:53:07 AM -07:00