Operador await – aguardar de forma assíncrona a conclusão da tarefa
O operador await
suspende a avaliação do método async delimitador enquanto a operação assíncrona representada por seu operando não é concluída. Quando a operação assíncrona for concluída, o operador await
retornará o resultado da operação, se houver. Quando o operador await
é aplicado ao operando que representa uma operação já concluída, ele retorna o resultado da operação imediatamente sem a suspensão do método delimitador. O operador await
não bloqueia o thread que avalia o método assíncrono. Quando o operador await
suspende o método assíncrono delimitador, o controle é retornado ao chamador do método.
No exemplo a seguir, o método HttpClient.GetByteArrayAsync retorna a instância Task<byte[]>
, que representa uma operação assíncrona que produz uma matriz de bytes quando é concluída. O operador await
suspende o método DownloadDocsMainPageAsync
até que a operação seja concluída. Quando DownloadDocsMainPageAsync
é suspenso, o controle é retornado ao método Main
, que é o chamador de DownloadDocsMainPageAsync
. O método Main
é executado até precisar do resultado da operação assíncrona executada pelo método DownloadDocsMainPageAsync
. Quando GetByteArrayAsync obtém todos os bytes, o restante do método DownloadDocsMainPageAsync
é avaliado. Depois disso, o restante do método Main
é avaliado.
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.
O operando de uma expressão await
deve fornecer uma notificação quando uma tarefa for concluída. Em geral, um delegado é invocado quando a tarefa é concluída com êxito ou sem êxito. A seção await
da especificação de linguagem C# fornece os detalhes sobre como essas notificações são implementadas.
O exemplo anterior usa o método assíncronoMain
. Para obter mais informações, confira a seção Operador await no método Main.
Observação
Para obter uma introdução à programação assíncrona, confira Programação assíncrona com async e await. A programação assíncrona com async
e await
segue o padrão assíncrono baseado em tarefas.
Use o operador await
somente em um método, uma expressão lambda ou um método anônimo que seja modificado pela palavra-chave async. Dentro de um método assíncrono, você não pode usar o operador await
no corpo de uma função local síncrona, dentro do bloco de uma instrução lock, e em um contexto inseguro.
O operando await
do operador geralmente é de um dos seguintes tipos .NET: Task, Task<TResult>, ValueTask ou ValueTask<TResult>. No entanto, qualquer expressão aguardável pode ser o operando do operador await
. Para obter mais informações, confira a seção Expressões aguardáveis da Especificação da linguagem C#.
O tipo de expressão await t
é TResult
se o tipo de expressão t
é Task<TResult> ou ValueTask<TResult>. Se o tipo de t
é Task ou ValueTask, o tipo de await t
é void
. Em ambos os casos, se t
gera uma exceção, await t
gera a exceção novamente.
Fluxos assíncronos e descartáveis
Você usa a instrução await foreach
para consumir um fluxo assíncrono de dados. Para obter mais informações, consulte a seção sobre a instrução foreach
do artigo Instruções de iteração.
Você usa a instrução await using
para trabalhar com um objeto assíncrono descartável, ou seja, um objeto de um tipo que implementa uma interface IAsyncDisposable. Para obter mais informações, consulte a seção Usar descartáveis assíncronos do artigo Implementar um método DisposeAsync.
Operador await no método Main
O método Main
, que é o ponto de entrada do aplicativo, pode retornar Task
ou Task<int>
, permitindo que ele seja assíncrono, de modo que você possa usar o operador await
no corpo. Em versões anteriores do C#, para garantir que o método Main
aguarde a conclusão de uma operação assíncrona, você pode recuperar o valor da propriedade Task<TResult>.Result da instância Task<TResult> retornada pelo método assíncrono correspondente. Para operações assíncronas que não produzem um valor, você pode chamar o método Task.Wait. Para saber mais sobre como selecionar a versão da linguagem, consulte Controle de versão da linguagem C#.
Especificação da linguagem C#
Para obter mais informações, confira a seção Expressões await da Especificação da linguagem C#.