await (Riferimenti per C#)await (C# Reference)

L'operatore await viene applicato a un'attività in un metodo asincrono per inserire un punto di sospensione nell'esecuzione del metodo fino al completamento dell'attività di cui si è in attesa.The await operator is applied to a task in an asynchronous method to insert a suspension point in the execution of the method until the awaited task completes. L'attività rappresenta il lavoro attualmente in fase di esecuzione.The task represents ongoing work.

È possibile usare await solo in un metodo asincrono modificato dalla parola chiave async.await can only be used in an asynchronous method modified by the async keyword. Tale metodo, definito usando il modificatore async e contenente di solito una o più espressioni await, viene denominato metodo asincrono.Such a method, defined by using the async modifier and usually containing one or more await expressions, is referred to as an async method.

Nota

Le parole chiave async e await sono state introdotte in C# 5.The async and await keywords were introduced in C# 5. Per un'introduzione alla programmazione asincrona, vedere Asynchronous Programming with async and await (Programmazione asincrona con async e await).For an introduction to async programming, see Asynchronous Programming with async and await.

L'attività a cui si applica l'operatore await viene in genere restituita da una chiamata a un metodo che implementa il modello asincrono basato su attività.The task to which the await operator is applied typically is returned by a call to a method that implements the Task-Based Asynchronous Pattern. Sono inclusi i metodi che restituiscono oggetti Task, Task<TResult>, ValueTask e ValueTask<TResult>.They include methods that return Task, Task<TResult>, ValueTask, and ValueTask<TResult> objects.

Nell'esempio seguente il metodo HttpClient.GetByteArrayAsync restituisce un oggetto Task<byte[]>.In the following example, the HttpClient.GetByteArrayAsync method returns a Task<byte[]>. L'attività è una promessa di produrre la matrice di byte effettiva una volta completata l'attività.The task is a promise to produce the actual byte array when the task is complete. L'operatore GetByteArrayAsync sospende l'esecuzione fino al completamento delle operazioni del metodo await.The await operator suspends execution until the work of the GetByteArrayAsync method is complete. Nel frattempo, il controllo viene restituito al chiamante di GetPageSizeAsync.In the meantime, control is returned to the caller of GetPageSizeAsync. Al termine dell'esecuzione dell'attività, l'espressione await restituisce una matrice di byte.When the task finishes execution, the await expression evaluates to a byte array.

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      string[] args = Environment.GetCommandLineArgs();
      if (args.Length > 1)
         GetPageSizeAsync(args[1]).Wait();
      else
         Console.WriteLine("Enter at least one URL on the command line.");
   }

   private static async Task GetPageSizeAsync(string url)  
   {  
       var client = new HttpClient();  
       var uri = new Uri(Uri.EscapeUriString(url));
       byte[] urlContents = await client.GetByteArrayAsync(uri);
       Console.WriteLine($"{url}: {urlContents.Length/2:N0} characters");  
   }  
}
// The following call from the command line:
//    await1 http://docs.microsoft.com
// displays output like the following: 
//   http://docs.microsoft.com: 7,967 characters


Importante

Per un esempio completo, vedere Procedura dettagliata: Accesso al Web con Async e Await.For the complete example, see Walkthrough: Accessing the Web by Using Async and Await. È possibile scaricare l'esempio da Developer Code Samples (Esempi di codice per sviluppatori) del sito Web Microsoft.You can download the sample from Developer Code Samples on the Microsoft website. L'esempio è nel progetto AsyncWalkthrough_HttpClient.The example is in the AsyncWalkthrough_HttpClient project.

Come mostrato nell'esempio precedente, se await viene applicato al risultato di una chiamata a un metodo che restituisce un elemento Task<TResult>, il tipo dell'espressione await è TResult.As shown in the previous example, if await is applied to the result of a method call that returns a Task<TResult>, then the type of the await expression is TResult. Se await viene applicato al risultato di una chiamata a un metodo che restituisce un elemento Task, il tipo dell'espressione await è void.If await is applied to the result of a method call that returns a Task, then the type of the await expression is void. Nell'esempio che segue viene illustrata la differenza.The following example illustrates the difference.

// await keyword used with a method that returns a Task<TResult>.  
TResult result = await AsyncMethodThatReturnsTaskTResult();  
  
// await keyword used with a method that returns a Task.  
await AsyncMethodThatReturnsTask();  

// await keyword used with a method that returns a ValueTask<TResult>.
TResult result = await AsyncMethodThatReturnsValueTaskTResult();

Un'espressione await non blocca il thread su cui è in esecuzione.An await expression does not block the thread on which it is executing. Comporta invece la registrazione, tramite il compilatore, della parte restante del metodo asincrono come continuazione dell'attività di cui si è in attesa.Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Il controllo quindi viene restituito al chiamante del metodo asincrono.Control then returns to the caller of the async method. Al termine dell'attività, ne richiama la continuazione e l'esecuzione del metodo asincrono riprende da dove era stata interrotta.When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

Un'espressione await può trovarsi solo nel corpo di un metodo che la contiene, di un'espressione lambda o di un metodo anonimo, che deve essere contrassegnato con un modificatore async.An await expression can occur only in the body of its enclosing method, lambda expression, or anonymous method, which must be marked with an async modifier. Il termine await funge da parola chiave solo in tale contesto.The term await serves as a keyword only in that context. Altrove, viene interpretata come identificatore.Elsewhere, it is interpreted as an identifier. All'interno del metodo, dell'espressione lambda o del metodo anonimo, un'espressione await non può trovarsi nel corpo di una funzione sincrona, in un'espressione di query, nel blocco di un'istruzione lock o in un contesto non sicuro.Within the method, lambda expression, or anonymous method, an await expression cannot occur in the body of a synchronous function, in a query expression, in the block of a lock statement, or in an unsafe context.

EccezioniExceptions

La maggior parte dei metodi asincroni restituisce Task o Task<TResult>.Most async methods return a Task or Task<TResult>. Le proprietà dell'attività restituita contengono informazioni sullo stato e sulla cronologia, ad esempio se l'attività è stata completata, se il metodo asincrono ha generato un'eccezione o è stato annullato e il risultato finale.The properties of the returned task carry information about its status and history, such as whether the task is complete, whether the async method caused an exception or was canceled, and what the final result is. L'operatore await accede a tali proprietà chiamando i metodi sull'oggetto restituito dal metodo GetAwaiter.The await operator accesses those properties by calling methods on the object returned by the GetAwaiter method.

Se si è in attesa di un metodo asincrono che restituisce un'attività che genera un'eccezione, l'operatore await genera di nuovo l'eccezione.If you await a task-returning async method that causes an exception, the await operator rethrows the exception.

Se si è in attesa di un metodo asincrono che restituisce un'attività che è stato annullato, tramite l'operatore await viene rigenerata un'eccezione OperationCanceledException.If you await a task-returning async method that's canceled, the await operator rethrows an OperationCanceledException.

Una singola attività in uno stato di errore può rispecchiare più eccezioni.A single task that is in a faulted state can reflect multiple exceptions. Ad esempio, l'attività può essere il risultato di una chiamata a Task.WhenAll.For example, the task might be the result of a call to Task.WhenAll. Quando si attende tale attività, l'operazione await rigenera solo una delle eccezioni.When you await such a task, the await operation rethrows only one of the exceptions. Tuttavia, non è possibile prevedere quale delle eccezioni verrà rigenerata.However, you can't predict which of the exceptions is rethrown.

Per esempi sulla gestione degli errori nei metodi asincroni, vedere try-catch.For examples of error handling in async methods, see try-catch.

EsempioExample

L'esempio seguente restituisce il numero totale di caratteri nelle pagine di cui gli URL vengono passati come argomenti della riga di comando.The following example returns the total number of characters in the pages whose URLs are passed to it as command line arguments. L'esempio chiama il metodo GetPageLengthsAsync, contrassegnato con la parola chiave async.The example calls the GetPageLengthsAsync method, which is marked with the async keyword. Il metodo GetPageLengthsAsync usa a sua volta la parola chiave await per attendere le chiamate del metodo HttpClient.GetStringAsync.The GetPageLengthsAsync method in turn uses the await keyword to await calls to the HttpClient.GetStringAsync method.

using System;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class Example
{
   static async Task Main()
   {
      string[] args = Environment.GetCommandLineArgs();
      if (args.Length < 2)
         throw new ArgumentNullException("No URIs specified on the command line.");

      // Don't pass the executable file name
      var uris = args.Skip(1).ToArray();

      long characters = await GetPageLengthsAsync(uris);
      Console.WriteLine($"{uris.Length} pages, {characters:N0} characters");
   }

   private static async Task<long> GetPageLengthsAsync(string[] uris)
   {
      var client = new HttpClient();
      long pageLengths = 0;

      foreach (var uri in uris)
      {
         var escapedUri = new Uri(Uri.EscapeUriString(uri));
         string pageContents = await client.GetStringAsync(escapedUri);
         Interlocked.Add(ref pageLengths, pageContents.Length);
      }
      
      return pageLengths;
   }
}

L'esempio precedente usa C# 7.1, che supporta il metodo async Main.The preceding example uses C# 7.1, which supports the async Main method. Poiché le versioni precedenti di C# non supportano i punti di ingresso dell'applicazione che restituiscono Task o Task<TResult>, non è possibile applicare il modificatore async al metodo Main e attendere la chiamata del metodo GetPageLengthsAsync.Because earlier C# versions don't support application entry points that return Task or Task<TResult>, you cannot apply the async modifier to the Main method and await the GetPageLengthsAsync method call. In tal caso, è possibile assicurarsi che il metodo Main resti in attesa del completamento dell'operazione asincrona recuperando il valore della proprietà Task<TResult>.Result.In that case, you can ensure that the Main method waits for the async operation to complete by retrieving the value of the Task<TResult>.Result property. Per le attività che non restituiscono un valore, è possibile chiamare il metodo Task.Wait.For tasks that do not return a value, you can call the Task.Wait method. Per informazioni su come selezionare la versione del linguaggio, vedere Selezionare la versione del linguaggio C#.For information about how to select the language version, see Select the C# language version.

Vedere ancheSee also