Condividi tramite


Programmazione asincrona con Async e Await (C# e Visual Basic)

È possibile evitare colli di bottiglia nelle prestazioni e migliorare la risposta generale dell'applicazione utilizzando la programmazione asincrona. Le tecniche tradizionali per la scrittura di applicazioni asincrone, tuttavia, possono essere complesse, rendendone difficile la scrittura, il debug e la gestione.

Visual Studio 2012 introduce un approccio semplificato, la programmazione asincrona, che sfrutta il supporto asincrono in .NET Framework 4.5 e Windows Runtime. Il compilatore esegue il lavoro difficile che prima veniva svolto dallo sviluppatore e l'applicazione mantiene una struttura logica simile al codice sincrono. Di conseguenza, si ottengono tutti i vantaggi della programmazione asincrona con meno lavoro richiesto.

Di seguito sono elencate le diverse sezioni di questo argomento.

  • Async migliora la velocità di risposta
  • I metodi asincroni sono più semplici da scrivere
  • Operazioni eseguite in un metodo asincrono
  • Metodi asincroni per API
  • Thread
  • Async e Await
  • Tipi restituiti e parametri
  • Convenzione di denominazione
  • Argomenti correlati
  • Esempio completo
  • Argomenti correlati

In questo argomento viene fornita una panoramica di come e quando utilizzare la programmazione asincrona e vengono forniti collegamenti per supportare gli argomenti contenenti informazioni dettagliate ed esempi.

Async migliora la velocità di risposta

La modalità asincrona è essenziale per le attività che potenzialmente bloccano l'esecuzione, ad esempio quando l'applicazione accede al Web. L'accesso a una risorsa Web può essere talvolta lento o ritardato. Se tale attività viene bloccata in un processo sincrono, l'intera applicazione deve attendere. In un processo asincrono l'applicazione può invece continuare con un altro lavoro che non dipende dalla risorsa Web finché l'attività di blocco non termina.

Nella tabella seguente sono mostrate le aree tipiche in cui la programmazione asincrona migliora la risposta. Le API elencate da .NET Framework 4.5 e Windows Runtime contengono metodi che supportano la programmazione asincrona.

Area dell'applicazione

API di supporto che contengono metodi asincroni

Accesso Web

HttpClient, SyndicationClient

Utilizzo dei file

StorageFile, StreamWriter, StreamReader, XmlReader

Utilizzo delle immagini

MediaCapture, BitmapEncoder, BitmapDecoder

Programmazione WCF

Operazioni sincrone e asincrone

La modalità asincrona è particolarmente importante per le applicazioni che accedono al thread dell'interfaccia utente poiché tutte le attività correlate all'interfaccia utente in genere condividono un thread. Se un processo è bloccato in un'applicazione sincrona, tutte le attività saranno bloccate. L'applicazione non risponde e si potrebbe pensare che si sia verificato un errore mentre si tratta solo di un'applicazione attesa.

Quando si utilizzano i metodi asincroni, l'applicazione continua a rispondere all'interfaccia utente. È possibile ad esempio ridimensionare o ridurre a icona una finestra oppure è possibile chiudere l'applicazione se non si desidera attendere il completamento.

L'approccio basato su modalità asincrona aggiunge l'equivalente di una trasmissione automatica all'elenco di opzioni da cui è possibile scegliere quando si progettano operazioni asincrone. In questo modo si ottengono tutti i vantaggi della programmazione asincrona tradizionale con meno lavoro richiesto allo sviluppatore.

I metodi asincroni sono più semplici da scrivere

Le parole chiave Async e Await in Visual Basic e le parole chiave async e await in C# sono il punto centrale della programmazione asincrona. Tramite queste due parole chiave, è possibile utilizzare le risorse di .NET Framework o di Windows Runtime per creare un metodo asincrono con la stessa facilità con cui è possibile creare un metodo sincrono. I metodi asincroni definiti mediante async e await sono denominati metodi asincroni.

Nell'esempio seguente viene illustrato un metodo asincrono. Quasi tutti gli elementi del codice dovrebbe essere completamente noti all'utente. I commenti richiamano le funzionalità che si aggiungono per creare la modalità asincrona.

È possibile trovare il file di esempio completo alla fine di questo argomento e scaricare l'esempio dalla pagina relativa all'esempio asincrono "Programmazione asincrona con async e await".

' Three things to note in the signature: 
'  - The method has an Async modifier.  
'  - The return type is Task or Task(Of T). (See "Return Types" section.) 
'    Here, it is Task(Of Integer) because the return statement returns an integer. 
'  - The method name ends in "Async."
Async Function AccessTheWebAsync() As Task(Of Integer)

    ' You need to add a reference to System.Net.Http to declare client. 
    Dim client As HttpClient = New HttpClient()

    ' GetStringAsync returns a Task(Of String). That means that when you await the 
    ' task you'll get a string (urlContents). 
    Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")


    ' You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork()

    ' The Await operator suspends AccessTheWebAsync. 
    '  - AccessTheWebAsync can't continue until getStringTask is complete. 
    '  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    '  - Control resumes here when getStringTask is complete.  
    '  - The Await operator then retrieves the string result from getStringTask. 
    Dim urlContents As String = Await getStringTask

    ' The return statement specifies an integer result. 
    ' Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    Return urlContents.Length
End Function
// Three things to note in the signature: 
//  - The method has an async modifier.  
//  - The return type is Task or Task<T>. (See "Return Types" section.)
//    Here, it is Task<int> because the return statement returns an integer. 
//  - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();

    // The await operator suspends AccessTheWebAsync. 
    //  - AccessTheWebAsync can't continue until getStringTask is complete. 
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    //  - Control resumes here when getStringTask is complete.  
    //  - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask;

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length;
}

Se AccessTheWebAsync non ha alcuna operazione da eseguire tra la chiamata di GetStringAsync e il relativo completamento, è possibile semplificare il codice chiamando l'istruzione singola seguente e rimanendo in attesa.

Dim urlContents As String = Await client.GetStringAsync()
string urlContents = await client.GetStringAsync();

Le seguenti caratteristiche riepilogano gli aspetti che rendono l'esempio precedente un metodo asincrono.

  • La firma del metodo include un modificatore Async o async.

  • Il nome di un metodo asincrono termina per convenzione con un suffisso "Async".

  • Il tipo di valore restituito è uno dei seguenti:

    • Task se nel metodo è presente un'istruzione return in cui l'operando è di tipo TResult.

    • Task se nel metodo non è presente un'istruzione return oppure è presente un'istruzione return senza l'operando.

    • Void (Sub in Visual Basic) se si sta scrivendo un gestore eventi asincrono.

    Per ulteriori informazioni, vedere la sezione "Tipi restituiti e parametri" più avanti in questo argomento.

  • Il metodo include in genere almeno un'espressione await, che contrassegna un punto in cui il metodo non può continuare fino a quando l'operazione asincrona attesa non sia completata. Nel frattempo, il metodo viene sospeso e il controllo ritorna al chiamante del metodo. Nella sezione successiva di questo argomento viene illustrato quello che accade in corrispondenza del punto di sospensione.

Nei metodi asincroni utilizzare le parole chiave e i tipi forniti per indicare l'operazione da eseguire e il compilatore esegue il resto dell'operazione, inclusa la traccia di cosa deve verificarsi quando il controllo viene restituito a un punto di attesa in un metodo sospeso. Alcuni processi di routine, come cicli e gestione delle eccezioni, possono essere difficili da gestire nel codice asincrono tradizionale. In un metodo asincrono scrivere questi elementi come in una soluzione sincrona e il problema viene risolto.

Per ulteriori informazioni sulla modalità asincrona in versioni precedenti di .NET Framework, vedere Task Parallel Library e programmazione asincrona .NET Framework tradizionale.

Operazioni eseguite in un metodo asincrono

La cosa più importante da capire nella programmazione asincrona è il modo in cui il flusso del controllo si sposta da un metodo all'altro. Nel diagramma seguente viene descritto il processo.

Tracciare un programma asincrono

I numeri nel diagramma corrispondono ai passaggi seguenti.

  1. Un gestore eventi chiama e attende il metodo asincrono AccessTheWebAsync.

  2. AccessTheWebAsync crea un'istanza di HttpClient e chiama il metodo asincrono GetStringAsync per scaricare il contenuto di un sito Web come stringa.

  3. Si verifica un evento in GetStringAsync che ne sospende lo stato di avanzamento forse perché deve attendere il termine dello scaricamento di un sito Web o un'altra attività di blocco. Per evitare di bloccare le risorse, GetStringAsync restituisce il controllo al chiamante AccessTheWebAsync.

    GetStringAsync restituisce Task dove TResult è una stringa e AccessTheWebAsync assegna le attività alla variabile getStringTask. L'attività rappresenta il processo in corso per la chiamata a GetStringAsync, con l'impegno di produrre un valore stringa effettivo a completamento del lavoro.

  4. Poiché getStringTask non è stata ancora attesa, AccessTheWebAsync può continuare con altro lavoro che non dipende dal risultato finale ottenuto da GetStringAsync. Tale lavoro è rappresentato da una chiamata al metodo sincrono DoIndependentWork.

  5. DoIndependentWork è un metodo sincrono che esegue il proprio lavoro e lo restituisce al chiamante.

  6. AccessTheWebAsync ha esaurito il lavoro che può eseguire senza un risultato da getStringTask. AccessTheWebAsync deve quindi calcolare e restituire la lunghezza della stringa scaricata, ma il metodo non può calcolare il valore finché quest'ultimo non contiene la stringa.

    Di conseguenza, AccessTheWebAsync utilizza un operatore await per sospendere lo stato di avanzamento e restituire il controllo al metodo che ha chiamato AccessTheWebAsync. AccessTheWebAsync restituisce Task(Of Integer) o Task<int> al chiamante. L'attività rappresenta l'intenzione di produrre un risultato di tipo Integer che è la lunghezza della stringa scaricata.

    Nota

    Se l'operazione GetStringAsync (e quindi getStringTask) viene completata prima che AccessTheWebAsync ne attenda il risultato, il controllo resta a AccessTheWebAsync.I costi per sospendere e tornare a AccessTheWebAsync sarebbero sprecati se il processo asincrono chiamato (getStringTask) fosse già completato e AccessTheWebSync non dovesse attendere il risultato finale.

    Nel chiamante (in questo esempio il gestore eventi), il modello di elaborazione continua. Il chiamante può eseguire altre attività che non dipendono dal risultato di AccessTheWebAsync prima di attendere tale risultato oppure può mettersi immediatamente in attesa. Il gestore eventi è in attesa di AccessTheWebAsync e AccessTheWebAsync è in attesa di GetStringAsync.

  7. GetStringAsync termina e produce un risultato di stringa. Il risultato di stringa non viene restituito dalla chiamata a GetStringAsync nel modo previsto. Tenere presente che il metodo non ha restituito un'attività al passaggio 3. Il risultato di stringa viene invece memorizzato nell'attività che rappresenta il completamento del metodo, ovvero getStringTask. L'operatore await recupera il risultato da getStringTask. L'istruzione di assegnazione assegna il risultato recuperato a urlContents.

  8. Quando AccessTheWebAsync ha il risultato di stringa, il metodo può calcolare la lunghezza della stringa. Il lavoro di AccessTheWebAsync è quindi completo e il gestore eventi in attesa può riprendere l'attività. Nell'esempio completo alla fine dell'argomento è possibile confermare che il gestore eventi recupera e stampa il valore del risultato di lunghezza.

Se non si ha familiarità con la programmazione asincrona, valutare la differenza tra il comportamento sincrono e asincrono. Viene restituito un metodo sincrono quando il lavoro è completato (passaggio 5), ma un metodo asincrono restituisce un valore di attività quando il relativo lavoro viene sospeso (passaggi 3 e 6). Una volta che il metodo asincrono completa l'operazione, l'attività viene contrassegnata come completata e il risultato, se disponibile, viene archiviato nell'attività.

Per ulteriori informazioni sul flusso di controllo, vedere Flusso di controllo in programmi asincroni (C# e Visual Basic).

Metodi asincroni per API

Metodi come GetStringAsync che supportano la programmazione asincrona sono utilizzabili in .NET Framework 4.5 in cui sono contenuti molti membri che utilizzano elementi async e await. È possibile riconoscere questi membri dal suffisso "Async" associato al nome del membro e dal tipo restituito di Task o di Task. Ad esempio, la classe System.IO.Stream contiene metodi come CopyToAsync, ReadAsync e WriteAsync insieme ai metodi sincroni CopyTo, Read e Write.

Windows Runtime contiene inoltre molti metodi utilizzabili con async e await nelle applicazioni Windows Store. Per ulteriori informazioni e metodi di esempio, vedere Guida introduttiva: utilizzo dell'operatore await per la programmazione asincrona, Programmazione asincrona (applicazioni di Windows Store) e WhenAny: bridging tra .NET Framework e Windows Runtime (C# e Visual Basic).

Thread

I metodi asincroni vengono considerati operazioni non bloccanti. Un'espressione await in un metodo asincrono non blocca il thread corrente quando l'attività attesa è in esecuzione. Al contrario, l'espressione registra il resto del metodo come continuazione e restituisce il controllo al chiamante del metodo asincrono.

Le parole chiave async e await non determinano la creazione di thread aggiuntivi. I metodi asincroni non richiedono multithreading perché un metodo asincrono non viene eseguito nel proprio thread. Il metodo viene eseguito nel contesto di sincronizzazione corrente e utilizza il tempo sul thread solo se il metodo è attivo. È possibile utilizzare Task.Run per spostare un lavoro associato alla CPU in un thread in background. Quest'ultimo tuttavia non è di alcun ausilio in un processo che attende solo che i risultati diventino disponibili.

L'approccio alla programmazione asincrona basato su async è quasi sempre preferibile agli approcci esistenti. In particolare, questo approccio è preferibile a BackgroundWorker per le operazioni di I/O poiché il codice è più semplice e non è necessario proteggersi da situazioni di race condition. Insieme a Task.Run, la programmazione asincrona è migliore di BackgroundWorker per le operazioni associate alla CPU perché separa i dettagli di coordinamento per l'esecuzione del codice dal lavoro che Task.Run trasferisce al pool di thread.

Async e Await

Se si specifica che un metodo è asincrono tramite un modificatore Async o async, attivare le due funzionalità seguenti.

  • Il metodo asincrono contrassegnato può utilizzare Await o await per definire i punti di sospensione. L'operatore await indica al compilatore che il metodo asincrono non può continuare oltre un dato punto prima del completamento del processo asincrono in attesa. Nel frattempo il controllo viene restituito al chiamante del metodo asincrono.

    La sospensione di un metodo asincrono in corrispondenza di un'espressione await non costituisce l'uscita dal metodo e i blocchi finally non vengono eseguiti.

  • Il metodo asincrono contrassegnato può essere atteso da metodi che lo chiamano.

Un metodo asincrono contiene in genere una o più occorrenze dell'operatore await, mentre l'assenza di espressioni await non provoca un errore del compilatore. Se un metodo asincrono non utilizza un operatore await per contrassegnare un punto di sospensione, si comporterà come un metodo sincrono nonostante la presenza del modificatore async. Il compilatore genera un avviso per tali metodi.

Async, async, Await e await rappresentano parole chiave contestuali. Per ulteriori informazioni ed esempi, vedere gli argomenti seguenti:

Tipi restituiti e parametri

Nella programmazione .NET Framework un metodo asincrono in genere restituisce Task o Task. In un metodo asincrono un operatore await viene applicato a un'attività restituita da una chiamata a un altro metodo asincrono.

Specificare Task come tipo restituito se il metodo contiene un'istruzione Return (Visual Basic) o return (C#) che specifica un operando di tipo TResult.

Utilizzare Task come tipo restituito se il metodo non include un'istruzione return o contiene un'istruzione return che non restituisce un operando.

Di seguito viene illustrato come dichiarare e chiamare un metodo che restituisce Task o Task.

' Signature specifies Task(Of Integer)
Async Function TaskOfTResult_MethodAsync() As Task(Of Integer)

    Dim hours As Integer
    ' . . .
    ' Return statement specifies an integer result.
    Return hours
End Function

' Calls to TaskOfTResult_MethodAsync
Dim returnedTaskTResult As Task(Of Integer) = TaskOfTResult_MethodAsync()
Dim intResult As Integer = Await returnedTaskTResult
' or, in a single statement
Dim intResult As Integer = Await TaskOfTResult_MethodAsync()


' Signature specifies Task
Async Function Task_MethodAsync() As Task

    ' . . .
    ' The method has no return statement.
End Function

' Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync()
Await returnedTask
' or, in a single statement
Await Task_MethodAsync()
// Signature specifies Task<TResult>
async Task<int> TaskOfTResult_MethodAsync()
{
    int hours;
    // . . .
    // Return statement specifies an integer result.
    return hours;
}

// Calls to TaskOfTResult_MethodAsync
Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
int intResult = await returnedTaskTResult;
// or, in a single statement
int intResult = await TaskOfTResult_MethodAsync();


// Signature specifies Task
async Task Task_MethodAsync()
{
    // . . .
    // The method has no return statement.  
}

// Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync();
await returnedTask;
// or, in a single statement
await Task_MethodAsync();

Ogni attività restituita rappresenta il lavoro attualmente in fase di esecuzione. Un'attività include le informazioni sullo stato del processo asincrono e, infine, il risultato finale del processo o l'eccezione che il processo genera se non viene completato.

Un metodo async può essere anche un metodo Sub (Visual Basic) o avere un tipo restituito void (C#). Il tipo restituito viene utilizzato principalmente per definire i gestori eventi, dove un tipo restituito void è necessario. I gestori eventi asincroni fungono spesso da punto di partenza per i programmi asincroni.

Un metodo asincrono che è una routine Sub o con un tipo restituito void non può essere atteso e il chiamante di un metodo che restituisce void non può rilevare eventuali eccezioni generate dal metodo.

Un metodo asincrono non può dichiarare i parametri ByRef in Visual Basic o i parametri ref o out in C#, ma il metodo può chiamare i metodi che presentano tali parametri.

Per ulteriori informazioni ed esempi, vedere Tipi restituiti asincroni (C# e Visual Basic). Per ulteriori informazioni su come rilevare eccezioni nei metodi asincroni, vedere try-catch (Riferimenti per C#) o Istruzione Try...Catch...Finally (Visual Basic).

Alle API asincrone nella programmazione Windows Runtime è associato uno dei seguenti tipi restituiti, che sono simili alle attività:

Per ulteriori informazioni e un esempio, vedere Guida introduttiva: utilizzo dell'operatore await per la programmazione asincrona.

Convenzione di denominazione

Per convenzione, aggiungere il suffisso "Async" ai nomi dei metodi che presentano un modificatore Async o async.

È possibile ignorare la convenzione se un evento, una classe base o un contratto di interfaccia suggerisce un nome diverso. Ad esempio, non è necessario rinominare i gestori eventi comuni, come Button1_Click.

Argomenti correlati

Titolo

Descrizione

Esempio

Procedura dettagliata: accesso al Web tramite Async e Await (C# e Visual Basic)

Mostra come convertire una soluzione WPF sincrona in una soluzione WPF asincrona. L'applicazione scarica una serie di siti Web.

Esempio asincrono: accesso alla procedura dettagliata Web (C# e Visual Basic)

Procedura: estendere la procedura dettagliata asincrona tramite Task.WhenAll (C# e Visual Basic)

Aggiunge Task.WhenAll alla procedura dettagliata precedente. L'utilizzo di WhenAll consente di avviare tutti i download contemporaneamente.

Procedura: effettuare più richieste Web in parallelo tramite Async e Await (C# e Visual Basic)

Viene illustrato come avviare contemporaneamente diverse attività.

Esempio asincrono: esecuzione di più richieste Web in parallelo (C# e Visual Basic)

Tipi restituiti asincroni (C# e Visual Basic)

Vengono illustrati i tipi che i metodi asincroni possono restituire e viene spiegato quando ogni tipo è appropriato.

Flusso di controllo in programmi asincroni (C# e Visual Basic)

Traccia in dettaglio il flusso di controllo con una successione di espressioni await in un programma asincrono.

Esempio asincrono: flusso di controllo nei programmi asincroni (C# e Visual Basic)

Ottimizzazione dell'applicazione Async (C# e Visual Basic)

Mostra come aggiungere la seguente funzionalità alla soluzione asincrono:

Esempio asincrono: ottimizzazione dell'applicazione (C# e Visual Basic)

Gestione della reentrancy nelle applicazioni asincrone (C# e Visual Basic)

Viene illustrato come gestire i casi in cui un'operazione asincrona attiva viene riavviata mentre è in esecuzione.

WhenAny: bridging tra .NET Framework e Windows Runtime (C# e Visual Basic)

Viene illustrato come integrare i tipi di attività in .NET Framework e IAsyncOperations in Windows Runtime per utilizzare WhenAny``1 con un metodo Windows Runtime.

Esempio asincrono: bridging tra .NET e Windows Runtime (AsTask e WhenAny)

Annullamento asincrono: bridging tra .NET Framework e Windows Runtime (C# e Visual Basic)

Viene illustrato come integrare i tipi di attività in .NET Framework e IAsyncOperations in Windows Runtime per utilizzare CancellationTokenSource con un metodo Windows Runtime.

Esempio asincrono: bridging tra .NET e Windows Runtime (AsTask e annullamento)

Utilizzo della funzionalità Async per l'accesso ai file (C# e Visual Basic)

Vengono elencati e illustrati i vantaggi dell'utilizzo di async e await per accedere ai file.

Procedura dettagliata: utilizzo del debugger con metodi Async

Viene illustrato il flusso di controllo in un'istruzione await e il comportamento dei comandi Esegui istruzione, Esegui istruzione/routinee Esci da istruzione/routine nei metodi asincroni.

Modello asincrono basato su attività (TAP)

Descrive un nuovo modello per la modalità asincrona in .NET Framework. Il modello è basato sui tipi Task e Task.

Guida rapida: chiamata ad API asincrone in C# o Visual Basic

Mostra come utilizzare async e await in un'applicazione Windows Store.

Programmazione asincrona (applicazioni Windows Store)

Viene fornita una descrizione generale della programmazione asincrona in Windows Runtime.

Video sulla modalità asincrona su Channel 9

Vengono forniti collegamenti a una serie di video sulla programmazione asincrona.

Esempio completo

Il codice seguente rappresenta il file MainWindow.xaml.vb o MainWindow.xaml.cs dell'applicazione Windows Presentation Foundation (WPF) discussa in questo argomento. È possibile scaricare l'esempio dalla pagina relativa all'esempio asincrono "Programmazione asincrona con async e await".

' Add an Imports statement and a reference for System.Net.Http 
Imports System.Net.Http

Class MainWindow

    ' Mark the event handler with async so you can use Await in it. 
    Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)

        ' Call and await separately. 
        'Task<int> getLengthTask = AccessTheWebAsync(); 
        '' You can do independent work here. 
        'int contentLength = await getLengthTask; 

        Dim contentLength As Integer = Await AccessTheWebAsync()

        ResultsTextBox.Text &=
            String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength)
    End Sub 


    ' Three things to note in the signature: 
    '  - The method has an Async modifier.  
    '  - The return type is Task or Task(Of T). (See "Return Types" section.) 
    '    Here, it is Task(Of Integer) because the return statement returns an integer. 
    '  - The method name ends in "Async."
    Async Function AccessTheWebAsync() As Task(Of Integer)

        ' You need to add a reference to System.Net.Http to declare client. 
        Dim client As HttpClient = New HttpClient()

        ' GetStringAsync returns a Task(Of String). That means that when you await the 
        ' task you'll get a string (urlContents). 
        Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")


        ' You can do work here that doesn't rely on the string from GetStringAsync.
        DoIndependentWork()

        ' The Await operator suspends AccessTheWebAsync. 
        '  - AccessTheWebAsync can't continue until getStringTask is complete. 
        '  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
        '  - Control resumes here when getStringTask is complete.  
        '  - The Await operator then retrieves the string result from getStringTask. 
        Dim urlContents As String = Await getStringTask

        ' The return statement specifies an integer result. 
        ' Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
        Return urlContents.Length
    End Function 


    Sub DoIndependentWork()
        ResultsTextBox.Text &= "Working . . . . . . ." & vbCrLf
    End Sub 
End Class 

' Sample Output: 

' Working . . . . . . . 

' Length of the downloaded string: 41763.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// Add a using directive and a reference for System.Net.Http; 
using System.Net.Http;

namespace AsyncFirstExample
{
    public partial class MainWindow : Window
    {
        // Mark the event handler with async so you can use await in it. 
        private async void StartButton_Click(object sender, RoutedEventArgs e)
        {
            // Call and await separately. 
            //Task<int> getLengthTask = AccessTheWebAsync(); 
            //// You can do independent work here. 
            //int contentLength = await getLengthTask; 

            int contentLength = await AccessTheWebAsync();

            resultsTextBox.Text +=
                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
        }


        // Three things to note in the signature: 
        //  - The method has an async modifier.  
        //  - The return type is Task or Task<T>. (See "Return Types" section.)
        //    Here, it is Task<int> because the return statement returns an integer. 
        //  - The method name ends in "Async."
        async Task<int> AccessTheWebAsync()
        { 
            // You need to add a reference to System.Net.Http to declare client.
            HttpClient client = new HttpClient();

            // GetStringAsync returns a Task<string>. That means that when you await the 
            // task you'll get a string (urlContents).
            Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");

            // You can do work here that doesn't rely on the string from GetStringAsync.
            DoIndependentWork();

            // The await operator suspends AccessTheWebAsync. 
            //  - AccessTheWebAsync can't continue until getStringTask is complete. 
            //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
            //  - Control resumes here when getStringTask is complete.  
            //  - The await operator then retrieves the string result from getStringTask. 
            string urlContents = await getStringTask;

            // The return statement specifies an integer result. 
            // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
            return urlContents.Length;
        }


        void DoIndependentWork()
        {
            resultsTextBox.Text += "Working . . . . . . .\r\n";
        }
    }
}

// Sample Output: 

// Working . . . . . . . 

// Length of the downloaded string: 41564.

Vedere anche

Riferimenti

async (Riferimenti per C#)

await (Riferimenti per C#)

Opertore Await (Visual Basic)

Async (Visual Basic)

Altre risorse

Esempio: programmazione asincrona in .NET per applicazioni di Windows Store

Esempio: realizzazione di un servizio WebClient con await

Esempio (C#): salvare una raccolta nell'archiviazione di applicazioni

Esempio (Visual Basic): salvare una raccolta nell'archiviazione di applicazioni