Operatore await: attende in modo asincrono il completamento di un'attività
L'operatore await
sospende la valutazione del metodo async contenitore fino al completamento dell'operazione asincrona rappresentata dal rispettivo operando. Quando l'operazione asincrona viene completata, l'operatore await
restituisce il risultato dell'operazione, se disponibile. Quando l'operatore await
viene applicato all'operando che rappresenta un'operazione già completata, restituisce il risultato dell'operazione immediatamente, senza sospensione del metodo contenitore. L'operatore await
non blocca il thread che valuta il metodo async. Quando l'operatore await
sospende il metodo asicrono contenitore, il controllo torna al chiamante del metodo.
Nell'esempio seguente il metodo HttpClient.GetByteArrayAsync restituisce l'istanza Task<byte[]>
, che rappresenta un'operazione asincrona che produce una matrice di byte quando viene completata. Fino al completamento dell'operazione, l'operatore await
sospende il metodo DownloadDocsMainPageAsync
. Quando DownloadDocsMainPageAsync
viene sospeso, il controllo viene restituito al metodo Main
, che è il chiamante di DownloadDocsMainPageAsync
. Il metodo Main
viene eseguito fino a quando non è necessario il risultato dell'operazione asincrona eseguita dal metodo DownloadDocsMainPageAsync
. Quando GetByteArrayAsync ottiene tutti i byte, viene valutato il resto del metodo DownloadDocsMainPageAsync
. Successivamente, viene valutato il resto del metodo Main
.
public class AwaitOperator
{
public static async Task Main()
{
Task<int> downloading = DownloadDocsMainPageAsync();
Console.WriteLine($"{nameof(Main)}: Launched downloading.");
int bytesLoaded = await downloading;
Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes.");
}
private static async Task<int> DownloadDocsMainPageAsync()
{
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading.");
var client = new HttpClient();
byte[] content = await client.GetByteArrayAsync("https://learn.microsoft.com/en-us/");
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading.");
return content.Length;
}
}
// Output similar to:
// DownloadDocsMainPageAsync: About to start downloading.
// Main: Launched downloading.
// DownloadDocsMainPageAsync: Finished downloading.
// Main: Downloaded 27700 bytes.
L'operando di un'espressione await
deve fornire una notifica al completamento di un'attività. In generale, viene richiamato un delegato quando l'attività viene completata, con esito positivo o negativo. La sezione await
della specifica del linguaggio C# fornisce informazioni dettagliate su come vengono implementate queste notifiche.
Nell'esempio precedente viene utilizzato il metodo asincrono Main
. Per altre informazioni, vedere la sezione Operatore await nel metodo Main.
Nota
Per un'introduzione alla programmazione asincrona, vedere Programmazione asincrona con async e await. La programmazione asincrona con async
e await
segue il modello asincrono basato su attività.
È possibile usare l'operatore await
solo in un metodo, in un'espressione lambda o in un metodo anonimo modificato dalla parola chiave async. All'interno di un metodo asincrono, non è possibile usare l'operatore await
nel corpo di una funzione locale sincrona, all'interno del blocco di un'istruzione lock e in un contesto unsafe.
L'operando dell'operatore await
è in genere di uno dei tipi .NET seguenti: Task, Task<TResult>, ValueTask o ValueTask<TResult>. Qualsiasi espressione awaitable, tuttavia, può essere l'operando dell'operatore await
. Per altre informazioni, vedere la sezione Espressioni awaitable in Specifica del linguaggio C#.
Il tipo di espressione await t
è TResult
se il tipo di espressione t
è Task<TResult> o ValueTask<TResult>. Se il tipo di t
è Task o ValueTask, il tipo di await t
è void
. In entrambi i casi, se t
genera un'eccezione, await t
genera nuovamente l'eccezione.
Flussi asincroni ed elementi eliminabili
Usare l'istruzione await foreach
per utilizzare un flusso asincrono di dati. Per altre informazioni, vedere la sezione relativa all'istruzione foreach
dell'articolo Istruzioni di iterazione.
Usare l'istruzione await using
per utilizzare un oggetto eliminabile in modo asincrono, ovvero un oggetto di un tipo che implementa un'interfaccia IAsyncDisposable. Per altre informazioni, vedere la sezione Uso di un elemento asincrono eliminabile nell'articolo Implementare un metodo DisposeAsync.
Operatore await nel metodo Main
Il metodo Main
, che è il punto di ingresso dell'applicazione, può restituire Task
o Task<int>
, consentendo che sia asincrono, in modo da poter usare l'operatore await
nel corpo. Nelle versioni di C# precedenti, per garantire che il metodo Main
attenda il completamento di un'operazione asincrona, è possibile recuperare il valore della proprietà Task<TResult>.Result dell'istanza di Task<TResult> restituita dal metodo asincrono corrispondente. Per le operazioni asincrone che non producono un valore, è possibile chiamare il metodo Task.Wait. Per informazioni su come selezionare la versione del linguaggio, vedere Controllo delle versioni del linguaggio C#.
Specifiche del linguaggio C#
Per altre informazioni, vedere la sezione Espressioni await in Specifica del linguaggio C#.