Panoramica del supporto asincrono
C# 5 ha introdotto due parole chiave per semplificare il programma asincrono: async e await. Queste parole chiave consentono di scrivere codice semplice che usa Task Parallel Library per eseguire operazioni a esecuzione prolungata ,ad esempio l'accesso alla rete, in un altro thread e accedere facilmente ai risultati al completamento. Le versioni più recenti di Xamarin.iOS e Xamarin.Android supportano async e await. Questo documento fornisce spiegazioni e un esempio di uso della nuova sintassi con Xamarin.
Il supporto asincrono di Xamarin è basato sulla base di Mono 3.0 e aggiorna il profilo API dalla versione di Silverlight per dispositivi mobili per essere una versione di .NET 4.5 per dispositivi mobili.
Panoramica
Questo documento presenta le nuove parole chiave async e await e illustra alcuni semplici esempi che implementano metodi asincroni in Xamarin.iOS e Xamarin.Android.
Per una descrizione più completa delle nuove funzionalità asincrone di C# 5 (inclusi molti esempi e diversi scenari di utilizzo) vedere l'articolo Programmazione asincrona.
L'applicazione di esempio effettua una semplice richiesta Web asincrona (senza bloccare il thread principale) quindi aggiorna l'interfaccia utente con il numero di caratteri e html scaricato.
Il supporto asincrono di Xamarin si basa sulla base di Mono 3.0 e aggiorna il profilo API dalla versione di Silverlight per dispositivi mobili per essere una versione di .NET 4.5 per dispositivi mobili.
Requisiti
Le funzionalità C# 5 richiedono Mono 3.0 incluso in Xamarin.iOS 6.4 e Xamarin.Android 4.8. Verrà richiesto di aggiornare Mono, Xamarin.iOS, Xamarin.Android e Xamarin.Mac per sfruttarne i vantaggi.
Uso di async & await
async
e await
sono nuove funzionalità del linguaggio C# che funzionano insieme a Task Parallel Library per semplificare la scrittura di codice threadato per eseguire attività a esecuzione prolungata senza bloccare il thread principale dell'applicazione.
async
Dichiarazione
La async
parola chiave viene inserita in una dichiarazione di metodo (o in un metodo lambda o anonimo) per indicare che contiene codice che può essere eseguito in modo asincrono, ovvero non bloccare il thread del chiamante.
Un metodo contrassegnato con async
deve contenere almeno un'espressione o un'istruzione await. Se nel metodo non await
sono presenti istruzioni, verrà eseguita in modo sincrono (come se non fosse presente alcun async
modificatore). Verrà generato anche un avviso del compilatore , ma non un errore.
Tipi restituiti
Un metodo asincrono deve restituire un Task
oggetto o Task<TResult>
void
.
Specificare il Task
tipo restituito se il metodo non restituisce alcun altro valore.
Specificare Task<TResult>
se il metodo deve restituire un valore, dove TResult
è il tipo restituito, ad esempio , int
.
Il void
tipo restituito viene usato principalmente per i gestori eventi che lo richiedono. Il codice che chiama metodi asincroni che restituiscono void non await
può essere eseguito sul risultato.
Parametri
I metodi asincroni non possono dichiarare ref
o out
parametri.
await
L'operatore await può essere applicato a un oggetto Task all'interno di un metodo contrassegnato come asincrono. Fa sì che il metodo arresti l'esecuzione a quel punto e attenda il completamento dell'attività.
L'uso di await non blocca il thread del chiamante, ma il controllo viene restituito al chiamante. Ciò significa che il thread chiamante non è bloccato, quindi, ad esempio, il thread dell'interfaccia utente non verrà bloccato quando si attende un'attività.
Al termine dell'attività, il metodo riprende l'esecuzione nello stesso punto del codice. Ciò include la restituzione all'ambito try di un blocco try-catch-finally (se presente). await non può essere usato in un blocco catch o finally.
Altre informazioni su await.
Gestione delle eccezioni
Le eccezioni che si verificano all'interno di un metodo asincrono vengono archiviate nell'attività e generate quando l'attività è await
ed. Queste eccezioni possono essere rilevate e gestite all'interno di un blocco try-catch.
Annullamento
I metodi asincroni che richiedono molto tempo per il completamento devono supportare l'annullamento. In genere, l'annullamento viene richiamato come segue:
- Viene creato un
CancellationTokenSource
oggetto . - L'istanza
CancellationTokenSource.Token
viene passata a un metodo asincrono annullabile. - L'annullamento viene richiesto chiamando il
CancellationTokenSource.Cancel
metodo .
L'attività annulla quindi se stessa e riconosce l'annullamento.
Per altre informazioni sull'annullamento, vedere Ottimizzazione dell'app asincrona (C#).
Esempio
Scaricare l'esempio (per iOS e Android) per visualizzare un esempio funzionante di async
e await
nelle app per dispositivi mobili. Il codice di esempio viene illustrato in modo più dettagliato in questa sezione.
Scrittura di un metodo asincrono
Il metodo seguente illustra come codificare un async
metodo con un'attività await
ed:
public async Task<int> DownloadHomepage()
{
var httpClient = new HttpClient(); // Xamarin supports HttpClient!
Task<string> contentsTask = httpClient.GetStringAsync("https://visualstudio.microsoft.com/xamarin"); // async method!
// await! control returns to the caller and the task continues to run on another thread
string contents = await contentsTask;
ResultEditText.Text += "DownloadHomepage method continues after async call. . . . .\n";
// After contentTask completes, you can calculate the length of the string.
int exampleInt = contents.Length;
ResultEditText.Text += "Downloaded the html and found out the length.\n\n\n";
ResultEditText.Text += contents; // just dump the entire HTML
return exampleInt; // Task<TResult> returns an object of type TResult, in this case int
}
Tenere presente quanto segue:
- La dichiarazione del metodo include la
async
parola chiave . - Il tipo restituito è
Task<int>
in modo che il codice chiamante possa accedere alint
valore calcolato in questo metodo. - L'istruzione return è
return exampleInt;
un oggetto integer, ovvero il fatto che il metodo restituisceTask<int>
fa parte dei miglioramenti del linguaggio.
Chiamata di un metodo asincrono 1
Questo pulsante click gestore eventi è reperibile nell'applicazione di esempio Android per chiamare il metodo descritto in precedenza:
GetButton.Click += async (sender, e) => {
Task<int> sizeTask = DownloadHomepage();
ResultTextView.Text = "loading...";
ResultEditText.Text = "loading...\n";
// await! control returns to the caller
var intResult = await sizeTask;
// when the Task<int> returns, the value is available and we can display on the UI
ResultTextView.Text = "Length: " + intResult ;
// "returns" void, since it's an event handler
};
Note:
- Il delegato anonimo ha il prefisso della parola chiave asincrona.
- Il metodo asincrono DownloadHomepage restituisce un oggetto Task<int> archiviato nella variabile sizeTask.
- Il codice è in attesa nella variabile sizeTask. Si tratta del percorso in cui il metodo viene sospeso e il controllo viene restituito al codice chiamante fino al termine dell'attività asincrona nel proprio thread.
- L'esecuzione non viene sospesa quando l'attività viene creata nella prima riga del metodo, nonostante l'attività creata in questa posizione. La parola chiave await indica la posizione in cui viene sospesa l'esecuzione.
- Al termine dell'attività asincrona, intResult viene impostato e l'esecuzione continua sul thread originale, dalla riga await.
Chiamata di un metodo asincrono 2
Nell'applicazione di esempio iOS l'esempio viene scritto leggermente in modo diverso per illustrare un approccio alternativo. Anziché usare un delegato anonimo, questo esempio dichiara un async
gestore eventi assegnato come un gestore eventi normale:
GetButton.TouchUpInside += HandleTouchUpInside;
Il metodo del gestore eventi viene quindi definito come illustrato di seguito:
async void HandleTouchUpInside (object sender, EventArgs e)
{
ResultLabel.Text = "loading...";
ResultTextView.Text = "loading...\n";
// await! control returns to the caller
var intResult = await DownloadHomepage();
// when the Task<int> returns, the value is available and we can display on the UI
ResultLabel.Text = "Length: " + intResult ;
}
Alcuni punti importanti:
- Il metodo è contrassegnato come
async
ma restituiscevoid
. Questa operazione viene in genere eseguita solo per i gestori eventi (in caso contrario si restituirà oTask
Task<TResult>
). - La
await
parola chiave nelDownloadHomepage
metodo assegna direttamente a una variabile (intResult
) a differenza dell'esempio precedente in cui è stata usata una variabile intermediaTask<int>
per fare riferimento all'attività. Si tratta della posizione in cui il controllo viene restituito al chiamante fino al completamento del metodo asincrono in un altro thread. - Quando il metodo asincrono viene completato e restituito, l'esecuzione riprende in corrispondenza del
await
che significa che il risultato intero viene restituito e quindi sottoposto a rendering in un widget dell'interfaccia utente.
Riepilogo
L'uso di async e await semplifica notevolmente il codice necessario per generare operazioni a esecuzione prolungata sui thread in background senza bloccare il thread principale. Semplificano anche l'accesso ai risultati quando l'attività è stata completata.
Questo documento ha fornito una panoramica delle nuove parole chiave del linguaggio ed esempi per Xamarin.iOS e Xamarin.Android.
Collegamenti correlati
- Callback come istruzione Go To della nostra generazione
- MapKitSearch (iOS) (esempio)
- Programmazione asincrona
- Ottimizzazione dell'applicazione Async (C#)
- Await, ui e deadlock. Oh mio Dio!
- Elaborazione delle attività al termine)
- Modello asincrono basato su attività (TAP)
- Asynchrony in C# 5 (blog di Eric Eseguireert) - sull'introduzione delle parole chiave