await (Referência de C#)await (C# Reference)

O operador await é aplicado a uma tarefa em um método assíncrono para inserir um ponto de suspensão na execução do método até que a tarefa aguardada seja concluída.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. A tarefa representa um trabalho em andamento.The task represents ongoing work.

await só pode ser usado em um método assíncrono modificado pela palavra-chave async.await can only be used in an asynchronous method modified by the async keyword. Esse tipo de método, definido pelo uso do modificador async e, geralmente, contendo uma ou mais expressões await, é conhecido como um método assíncrono.Such a method, defined by using the async modifier and usually containing one or more await expressions, is referred to as an async method.

Observação

As palavras-chave async e await foram introduzidas no C# 5.The async and await keywords were introduced in C# 5. Para uma introdução à programação assíncrona, consulte Programação assíncrona com async e await.For an introduction to async programming, see Asynchronous Programming with async and await.

A tarefa à qual o operador await é aplicado, normalmente é retornada por uma chamada a um método que implementa o Padrão assíncrono baseado em tarefa.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. Eles incluem métodos que retornam objetosTask, Task<TResult>, ValueTask e ValueTask<TResult>.They include methods that return Task, Task<TResult>, ValueTask, and ValueTask<TResult> objects.

No exemplo a seguir, o método HttpClient.GetByteArrayAsync retorna um Task<byte[]>.In the following example, the HttpClient.GetByteArrayAsync method returns a Task<byte[]>. A tarefa é uma promessa de produzir a matriz de bytes real quando a tarefa for concluída.The task is a promise to produce the actual byte array when the task is complete. O operador await suspende a execução até que o trabalho do método GetByteArrayAsync esteja concluído.The await operator suspends execution until the work of the GetByteArrayAsync method is complete. Enquanto isso, o controle é retornado ao chamador de GetPageSizeAsync.In the meantime, control is returned to the caller of GetPageSizeAsync. Quando a tarefa termina a execução, a expressão await é avaliada para uma matriz de bytes.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

Para o exemplo completo, confira o Passo a passo: Como acessar a Web usando Async e Await.For the complete example, see Walkthrough: Accessing the Web by Using Async and Await. Você pode baixar o exemplo em Exemplos de código do desenvolvedor no site da Microsoft.You can download the sample from Developer Code Samples on the Microsoft website. O exemplo está no projeto AsyncWalkthrough_HttpClient.The example is in the AsyncWalkthrough_HttpClient project.

Conforme mostrado no exemplo anterior, se await for aplicado ao resultado de uma chamada de método que retorna uma Task<TResult>, o tipo da expressão await será 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 for aplicado ao resultado de uma chamada de método que retorna uma Task, o tipo da expressão await será 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. O exemplo a seguir ilustra a diferença.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();

Um expressão await não bloqueia o thread no qual ela está em execução.An await expression does not block the thread on which it is executing. Em vez disso, ela faz com que o compilador inscreva o restante do método assíncrono como uma continuação da tarefa aguardada.Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Em seguida, o controle retorna para o chamador do método assíncrono.Control then returns to the caller of the async method. Quando a tarefa for concluída, ela invoca a sua continuação e a execução do método assíncrono continua de onde parou.When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

Uma expressão await só pode ocorrer no corpo do respectivo método delimitador, de uma expressão lambda ou de um método anônimo que deve estar marcado com um modificador 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. O termo await só serve como uma palavra-chave nesse contexto.The term await serves as a keyword only in that context. Em outro local, ele será interpretado como um identificador.Elsewhere, it is interpreted as an identifier. No método, na expressão lambda ou no método anônimo, uma expressão await não pode ocorrer no corpo de uma função síncrona, em uma expressão de consulta, no bloco de uma instrução lock ou em um contexto inseguro.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.

ExceçõesExceptions

A maioria dos métodos assíncronos retorna um Task ou um Task<TResult>.Most async methods return a Task or Task<TResult>. As propriedades da tarefa retornada transportam informações sobre seu status e histórico como: se a tarefa foi concluída, se o método assíncrono causou uma exceção ou se foi cancelado e qual foi o resultado final.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. O operador await acessa essas propriedades chamando métodos no objeto retornado pelo método GetAwaiter.The await operator accesses those properties by calling methods on the object returned by the GetAwaiter method.

Se você aguarda um método assíncrono de retorno de tarefa que causou uma exceção, o operador await relança a exceção.If you await a task-returning async method that causes an exception, the await operator rethrows the exception.

Se você aguarda um método assíncrono de retorno de tarefa que está cancelado, o operador await relança uma OperationCanceledException.If you await a task-returning async method that's canceled, the await operator rethrows an OperationCanceledException.

Uma tarefa única que está em um estado com falha pode refletir várias exceções.A single task that is in a faulted state can reflect multiple exceptions. Por exemplo, a tarefa pode ser o resultado de uma chamada para Task.WhenAll.For example, the task might be the result of a call to Task.WhenAll. Quando você aguarda essa tarefa, a operação de aguardar relança apenas uma das exceções.When you await such a task, the await operation rethrows only one of the exceptions. No entanto, você não pode prever qual das exceções será relançada.However, you can't predict which of the exceptions is rethrown.

Para obter exemplos de tratamento de erro em métodos assíncronos, consulte try-catch.For examples of error handling in async methods, see try-catch.

ExemploExample

O exemplo a seguir retorna o número total de caracteres nas páginas cujas URLs são passadas para ele como argumentos de linha de comando.The following example returns the total number of characters in the pages whose URLs are passed to it as command line arguments. O exemplo chama o método GetPageLengthsAsync, que é marcado com a palavra-chave async.The example calls the GetPageLengthsAsync method, which is marked with the async keyword. O método GetPageLengthsAsync, por sua vez, utiliza a palavra-chave await para aguardar chamadas para o método 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;
   }
}

O exemplo anterior usa o C# 7.1, que oferece suporte ao método async Main.The preceding example uses C# 7.1, which supports the async Main method. Como as versões anteriores de C# não dão suporte a pontos de entrada do aplicativo que retornam Task ou Task<TResult>, não é possível aplicar o modificador async ao método Main e esperar a chamada do método 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. Nesse caso, podemos assegurar que o método Main aguarde a conclusão da operação assíncrona por meio da recuperação do valor da propriedade 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. Para tarefas que não retornam um valor, você pode chamar o método Task.Wait.For tasks that do not return a value, you can call the Task.Wait method. Para saber mais sobre como selecionar a versão da linguagem, consulte Selecionar a versão da linguagem C#.For information about how to select the language version, see Select the C# language version.

Consulte tambémSee also