Compartilhar via


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.

A linguagem C# faz referência a documentos da versão mais recentemente lançada da linguagem C#. Ele também contém a documentação inicial para funcionalidades em pré-visualizações públicas para o próximo lançamento do idioma.

A documentação identifica qualquer recurso introduzido pela primeira vez nas três últimas versões do idioma ou nas versões prévias públicas atuais.

Dica

Para descobrir quando um recurso foi introduzido pela primeira vez em C#, consulte o artigo sobre o histórico de versão da linguagem C#.

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 Main método serve como o ponto de entrada do aplicativo. Ele pode retornar Task ou Task<int>, o que o torna assíncrono. Ao tornar o Main método assíncrono, você pode usar o await operador em seu corpo. Em versões anteriores do C#, para garantir que o Main método aguarde a conclusão de uma operação assíncrona, recupere o valor da Task<TResult>.Result propriedade da Task<TResult> instância que o método assíncrono correspondente retorna. Para operações assíncronas que não produzem um valor, chame o Task.Wait método. 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#.

Confira também