Operador Await (Visual Basic)

Você aplica o operador Await a um operando em um método assíncrono ou expressão lambda para suspender a execução do método até que a tarefa aguardada seja concluída. A tarefa representa um trabalho em andamento.

O método no qual Await é usado deve ter um modificador Async. 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.

Observação

As palavras-chave Async e Await foram introduzidas no Visual Studio 2012. Para uma introdução à programação assíncrona, consulte Programação assíncrona com Async e Await.

A tarefa à qual o operador Await é aplicado, normalmente é o valor retornado de uma chamada a um método que implementa o Padrão assíncrono baseado em tarefa, que é Task ou Task<TResult>.

No código a seguir, o método HttpClientGetByteArrayAsync retorna getContentsTask, um Task(Of Byte()). A tarefa é uma promessa de produzir a matriz de bytes real quando a operação for concluída. O operador Await é aplicado a getContentsTask para suspender a execução em SumPageSizesAsync até que getContentsTask seja concluída. Enquanto isso, o controle é retornado ao chamador de SumPageSizesAsync. Quando getContentsTask for concluído, a expressão Await resulta em uma matriz de bytes.

Private Async Function SumPageSizesAsync() As Task

    ' To use the HttpClient type in desktop apps, you must include a using directive and add a
    ' reference for the System.Net.Http namespace.
    Dim client As HttpClient = New HttpClient()
    ' . . .
    Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url)
    Dim urlContents As Byte() = Await getContentsTask

    ' Equivalently, now that you see how it works, you can write the same thing in a single line.
    'Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    ' . . .
End Function

Importante

Para obter o exemplo completo, consulte Passo a passo: acessando a Web usando async e await. Você pode baixar o exemplo do Navegador de Exemplo do .NET. O código de exemplo está no projeto SerialAsyncExample.

Se Await for aplicado ao resultado de uma chamada de método que retorna uma Task(Of TResult), o tipo da expressão Await será TResult. Se Await for aplicado ao resultado de uma chamada de método que retorna um Task, a expressão Await não retornará um valor. O exemplo a seguir ilustra a diferença.

' Await used with a method that returns a Task(Of TResult).
Dim result As TResult = Await AsyncMethodThatReturnsTaskTResult()

' Await used with a method that returns a Task.
Await AsyncMethodThatReturnsTask()

Uma expressão ou instrução Await não bloqueia o thread no qual está sendo executada. Em vez disso, ela faz com que o compilador inscreva o restante do método assíncrono, após a expressão Await, como uma continuação da tarefa aguardada. Em seguida, o controle retorna para o chamador do método assíncrono. 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.

Uma expressão Await pode ocorrer apenas no corpo de um método imediatamente delimitador ou expressão lambda marcada por um modificador Async. O termo Await só serve como uma palavra-chave nesse contexto. Em outro local, ele será interpretado como um identificador. Dentro do método Async ou da expressão lambda, uma expressão Await não pode ocorrer em uma expressão de consulta, no bloco Catch ou Finally de uma instrução Try…Catch…Finally, no loop expressão de variável de controle de um loop For ou For Each, ou no corpo de uma instrução SyncLock.

Exceções

A maioria dos métodos assíncronos retorna um Task ou um 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. O operador Await acessa essas propriedades.

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.

Se você aguarda um método assíncrono de retorno de tarefa que está cancelado, o operador Await relança uma OperationCanceledException.

Uma tarefa única que está em um estado com falha pode refletir várias exceções. Por exemplo, a tarefa pode ser o resultado de uma chamada para Task.WhenAll. Quando você aguarda essa tarefa, a operação de aguardar relança apenas uma das exceções. No entanto, você não pode prever qual das exceções será relançada.

Para obter exemplos de tratamento de erro em métodos assíncronos, confira Instrução Try...Catch...Finally.

Exemplo

O exemplo do Windows Forms a seguir ilustra o uso do Await em um método assíncrono WaitAsynchronouslyAsync. Compare o comportamento desse método com o comportamento de WaitSynchronously. Sem um operador Await, WaitSynchronously é executado de maneira síncrona, apesar do uso do modificador Async na definição e de uma chamada para Thread.Sleep no corpo.

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    ' Call the method that runs asynchronously.
    Dim result As String = Await WaitAsynchronouslyAsync()

    ' Call the method that runs synchronously.
    'Dim result As String = Await WaitSynchronously()

    ' Display the result.
    TextBox1.Text &= result
End Sub

' The following method runs asynchronously. The UI thread is not
' blocked during the delay. You can move or resize the Form1 window
' while Task.Delay is running.
Public Async Function WaitAsynchronouslyAsync() As Task(Of String)
    Await Task.Delay(10000)
    Return "Finished"
End Function

' The following method runs synchronously, despite the use of Async.
' You cannot move or resize the Form1 window while Thread.Sleep
' is running because the UI thread is blocked.
Public Async Function WaitSynchronously() As Task(Of String)
    ' Import System.Threading for the Sleep method.
    Thread.Sleep(10000)
    Return "Finished"
End Function

Confira também