Condividi tramite


Chiamare API asincrone in C# o Visual Basic

La piattaforma UWP (Universal Windows Platform) include molte API asincrone per garantire che l'app rimanga reattiva quando esegue lavori che potrebbero richiedere molto tempo. Questo argomento illustra come usare metodi asincroni dalla piattaforma UWP in C# o Microsoft Visual Basic.

Le API asincrone impediscono all'app di attendere il completamento di operazioni di grandi dimensioni prima di continuare l'esecuzione. Ad esempio, un'app che scarica info da Internet potrebbe rimanere in attesa parecchi secondi priva che l'info arrivi. Se si usa un metodo sincrono per recuperare le informazioni, l'app viene bloccata fino a quando il metodo non viene restituito. Un'app che non risponde all'interazione dell'utente e sembra bloccata può generare frustrazione nell'utente. Fornendo API asincrone, la piattaforma UWP consente di garantire che l'app rimanga reattiva all'utente quando esegue operazioni lunghe.

La maggior parte delle API asincrone nella piattaforma UWP non dispone di controparti sincrone, quindi devi essere sicuro di capire come usare le API asincrone con C# o Visual Basic nella tua app piattaforma UWP (Universal Windows Platform). Di seguito viene illustrato come chiamare LE API asincrone della piattaforma UWP.

Uso delle API asincrone

Per convenzione, ai metodi asincroni vengono assegnati nomi che terminano con "Async". In genere si chiamano API asincrone in risposta all'azione di un utente, ad esempio quando l'utente fa clic su un pulsante. La chiamata di un metodo asincrono in un gestore eventi è uno dei modi più semplici per usare le API asincrone. In questo esempio viene usato l'operatore await.

Si supponga di avere un'app che elenca i titoli dei post di blog da una determinata posizione. L'app ha un pulsante su cui l'utente fa clic per ottenere i titoli. I titoli vengono visualizzati in un controllo TextBlock. Quando l'utente fa clic sul pulsante, è importante che l'app rimanga reattiva mentre attende le informazioni dal sito Web del blog. Per garantire questa velocità di risposta, la piattaforma UWP fornisce un metodo asincrono, SyndicationClient.RetrieveFeedAsync, per scaricare il feed.

L'esempio seguente ottiene gli elenchi dei post di blog da un blog chiamando il metodo asincrono, SyndicationClient.RetrieveFeedAsync e attendendo il risultato.

// 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

Per questo esempio è necessario tenere presenti un paio di aspetti importanti. Prima di tutto, la riga, SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) usa l'operatore await con la chiamata al metodo asincrono, RetrieveFeedAsync. È possibile considerare l'operatore await come indicare al compilatore che si sta chiamando un metodo asincrono, che fa sì che il compilatore eseguono alcune operazioni aggiuntive in modo che non sia necessario. Successivamente, la dichiarazione del gestore eventi include la parola chiave asincrona. È necessario includere questa parola chiave nella dichiarazione del metodo di qualsiasi metodo in cui si usa l'operatore await.

In questo argomento non verranno esaminati molti dettagli sulle operazioni che il compilatore esegue con l'operatore await, ma esaminiamo le operazioni che l'app esegue in modo che sia asincrona e reattiva. Considerare cosa accade quando si usa codice sincrono. Si supponga, ad esempio, che sia presente un metodo denominato SyndicationClient.RetrieveFeed sincrono. (Non esiste un metodo di questo tipo, ma si supponga che esista). Se l'app include la riga SyndicationFeed feed = client.RetrieveFeed(feedUri), invece di SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), l'esecuzione dell'app viene arrestata fino a quando non è disponibile il valore restituito di RetrieveFeed. Mentre l'app attende il completamento del metodo, non può rispondere ad altri eventi, ad esempio un altro evento Click. Ovvero, l'app verrà bloccata fino a quando non viene restituito RetrieveFeed.

Tuttavia, se si chiama client.RetrieveFeedAsync, il metodo avvia il recupero e lo restituisce immediatamente. Quando si usa await con RetrieveFeedAsync, l'app esce temporaneamente dal gestore eventi. Può quindi elaborare altri eventi mentre RetrieveFeedAsync viene eseguito in modo asincrono. In questo modo l'app risponde all'utente. Quando RetrieveFeedAsync viene completato e SyndicationFeed è disponibile, l'app esegue essenzialmente il reinserimento del gestore eventi in cui è stata interrotta, dopo SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) e termina il resto del metodo.

L'aspetto interessante dell'uso dell'operatore await è che il codice non ha un aspetto molto diverso dal modo in cui il codice sembra se è stato usato il metodo immaginario RetrieveFeed. Esistono modi per scrivere codice asincrono in C# o Visual Basic senza l'operatore await, ma il codice risultante tende a evidenziare i meccanismi di esecuzione asincrona. In questo modo il codice asincrono risulta difficile da scrivere, difficile da comprendere e da gestire. Usando l'operatore await, si ottengono i vantaggi di un'app asincrona senza rendere complesso il codice.

Restituire tipi e risultati di API asincrone

Se è stato seguito il collegamento a RetrieveFeedAsync, si potrebbe aver notato che il tipo restituito di RetrieveFeedAsync non è un SyndicationFeed. Invece, il tipo restituito è IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>. Visualizzata dalla sintassi non elaborata, un'API asincrona restituisce un oggetto che contiene il risultato all'interno di esso. Sebbene sia comune e talvolta utile pensare a un metodo asincrono come awaitable, l'operatore await opera effettivamente sul valore restituito del metodo, non sul metodo. Quando si applica l'operatore await, ciò che si ottiene è il risultato della chiamata a GetResult sull'oggetto restituito dal metodo. Nell'esempio, SyndicationFeed è il risultato di RetrieveFeedAsync.GetResult().

Quando si usa un metodo asincrono, è possibile esaminare la firma per vedere cosa si otterrà dopo aver atteso il valore restituito dal metodo. Tutte le API asincrone nella piattaforma UWP restituiscono uno dei tipi seguenti:

Il tipo di risultato di un metodo asincrono è uguale al parametro di tipo TResult. I tipi senza TResult non hanno un risultato. Si può pensare al risultato come void. In Visual Basic una procedura Sub equivale a un metodo con un tipo void restituito.

La tabella seguente fornisce esempi di metodi asincroni ed elenca il tipo restituito e il tipo di risultato di ognuno.

Metodo asincrono Tipo restituito Tipo di risultato
SyndicationClient.RetrieveFeedAsync IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> SyndicationFeed
FileOpenPicker.PickSingleFileAsync IAsyncOperation<StorageFile> StorageFile
XmlDocument.SaveToFileAsync IAsyncAction void
InkStrokeContainer.LoadAsync IAsyncActionWithProgress<UInt64> void
DataReader.LoadAsync DataReaderLoadOperation, una classe di risultati personalizzata che implementa IAsyncOperation<UInt32> UInt32

 

I metodi asincroni definiti in .NET per app UWP hanno il tipo di ritorno Task o Task<TResult>. I metodi che restituiscono Task sono simili ai metodi asincroni nella piattaforma UWP che restituiscono IAsyncAction. In ogni caso, il risultato del metodo asincrono è void. Il tipo restituito Task<TResult> è simile a IAsyncOperation<TResult> in quanto il risultato del metodo asincrono quando si esegue l'attività è lo stesso tipo del parametro tipo TResult. Per altre info sull'uso di .NET per app UWP e attività UWP, vedere Panoramica di .NET per le app di Windows Runtime.

Gestione degli errori

Quando si usa l'operatore await per recuperare i risultati da un metodo asincrono, è possibile usare un blocco try/catch per gestire gli errori che si verificano nei metodi asincroni, proprio come per i metodi sincroni. Nell'esempio precedente viene eseguito il wrapping del metodo RetrieveFeedAsync e dell'operazione await in un blocco try/catch per gestire gli errori quando viene generata un'eccezione.

Quando i metodi asincroni chiamano altri metodi asincroni, qualsiasi metodo asincrono che genera un'eccezione verrà propagato ai metodi esterni. Ciò significa che è possibile inserire un blocco try/catch sul metodo più esterno per rilevare gli errori per i metodi asincroni annidati. Anche in questo caso, è simile a come intercettare le eccezioni per i metodi sincroni. Tuttavia, non è possibile usare await nel blocco catch.

Suggerimento A partire da C# in Microsoft Visual Studio 2005, è possibile usare await nel blocco catch.

Riepilogo e passaggi successivi

Il modello di chiamata di un metodo asincrono illustrato di seguito è quello più semplice da usare quando si chiamano API asincrone in un gestore eventi. È anche possibile utilizzare questo modello quando si chiama un metodo asincrono in un metodo sottoposto a override che restituisce void o sub in Visual Basic.

Quando si riscontrano metodi asincroni nella piattaforma UWP, è importante ricordare:

  • Per convenzione, ai metodi asincroni vengono assegnati nomi che terminano con "Async".
  • Qualsiasi metodo che usa l'operatore await deve avere la relativa dichiarazione contrassegnata con la parola chiave asincrona.
  • Quando un'app trova l'operatore await, l'app rimane reattiva all'interazione dell'utente mentre viene eseguito il metodo asincrono.
  • In attesa del valore restituito da un metodo asincrono restituisce un oggetto contenente il risultato. Nella maggior parte dei casi, il risultato contenuto all'interno del valore restituito è utile, non il valore restituito stesso. È possibile trovare il tipo del valore contenuto all'interno del risultato esaminando il tipo restituito del metodo asincrono.
  • L'uso di API asincrone e modelli asincroni è spesso un modo per migliorare la velocità di risposta dell'app.

L'esempio in questo argomento restituisce testo simile al seguente.

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