Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Windows include molte API asincrone per garantire che l'app rimanga reattiva quando funziona che potrebbe richiedere molto tempo. Questo argomento illustra come usare metodi asincroni 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 informazioni da Internet potrebbe trascorrere alcuni secondi in attesa dell'arrivo delle informazioni. Se usi un metodo sincrono per recuperare le informazioni, l'app viene bloccata fino a quando il metodo non viene restituito. L'app non risponderà all'interazione dell'utente e, poiché sembra non reattiva, l'utente potrebbe diventare frustrato. Fornendo API asincrone, Windows consente di garantire che l'app rimanga reattiva all'utente quando esegue operazioni lunghe.
La maggior parte delle API asincrone in Windows non dispone di controparti sincrone, quindi è necessario assicurarsi di comprendere come usare le API asincrone con C# o Visual Basic nell'app Windows. Di seguito viene illustrato come chiamare LE API asincrone.
Uso delle API asincrone
Per convenzione, ai metodi asincroni vengono assegnati nomi che terminano in "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 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, Windows 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
Questo esempio include un paio di aspetti importanti. Prima di tutto, SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) la riga usa l'operatore await con la chiamata al metodo asincrono RetrieveFeedAsync. Puoi considerare l'operatore await come un modo per indicare al compilatore che stai chiamando un metodo asincrono, il che induce il compilatore a svolgere del lavoro aggiuntivo al posto tuo. 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, la tua app rimarrebbe bloccata finché RetrieveFeed non restituisce un risultato.
Tuttavia, se si chiama client.RetrieveFeedAsync, il metodo avvia il recupero e restituisce immediatamente. Quando usi 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 è 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 restituiscono uno dei tipi seguenti:
- IAsyncOperation<TResult>
- IAsyncOperationWithProgress<TResult, TProgress>
- IAsyncAction
- IAsyncActionWithProgress<TProgress>
Il tipo di risultato di un metodo asincrono è uguale al parametro di TResult tipo . I tipi senza TResult non hanno un risultato. Si può pensare al risultato come vuoto. In Visual Basic, una procedura Sub equivale a un metodo con un tipo restituito void.
La tabella seguente fornisce esempi di metodi asincroni ed elenca il tipo restituito e il tipo di risultato di ognuno.
| Metodo asincrono | Tipo di ritorno | Tipo di risultato |
|---|---|---|
| SyndicationClient.RetrieveFeedAsync | IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> | SyndicationFeed |
| FileOpenPicker.PickSingleFileAsync | IAsyncOperation<StorageFile> | File di archiviazione |
| XmlDocument.SaveToFileAsync | IAsyncAction | void |
| InkStrokeContainer.LoadAsync | IAsyncActionWithProgress<UInt64> | void |
| DataReader.LoadAsync | DataReaderLoadOperation, una classe di risultati personalizzata che implementa IAsyncOperation<UInt32> | UInt32 |
Note
FileOpenPicker e altre API di selezione richiedono l'inizializzazione dell'handle di finestra (HWND) nelle app desktop WinUI 3. Prima di chiamare PickSingleFileAsync, richiama WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd), dove hwnd deriva da WindowNative.GetWindowHandle(this). Vedi API del selettore WinUI 3 che richiedono un handle di finestra (HWND).
I metodi asincroni definiti in .NET per le app Windows hanno il tipo restituito Task o Task<TResult>. I metodi che restituiscono Task sono simili ai metodi asincroni 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 TResult parametro di tipo.
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 .
Tip
A partire da C# 6.0 (.NET Framework 4.6 / Visual Studio 2015), è 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 usare 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, è importante ricordare:
- Per convenzione, ai metodi asincroni vengono assegnati nomi che terminano in "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