Await (Operador) (Visual Basic)

El operador Await se aplica a un operando de un método asincrónico o a una expresión lambda para suspender la ejecución del método hasta que la tarea en espera se complete. La tarea representa el trabajo en curso.

El método en el que se utiliza Await debe tener un modificador Async. Este tipo de método, que se define mediante el modificador Async y que generalmente contiene una o más expresiones Await, se denomina método asincrónico.

Nota

Las palabras clave Async y Await se incluyeron en Visual Studio 2012. Para una introducción a la programación asincrónica, consulte Programación asincrónica con Async y Await.

Por lo general, la tarea a la que se aplica el operador Await es el valor devuelto de una llamada a un método que implementa el modelo asincrónico basado en tareas, es decir, un elemento Task o Task<TResult>.

En el código siguiente, el método HttpClientGetByteArrayAsync devuelve getContentsTask, un tipo Task(Of Byte()). La tarea garantiza que la matriz de bytes real se generará cuando finalice la operación. El operador Await se aplica a getContentsTask para suspender la ejecución en SumPageSizesAsync hasta que se complete getContentsTask. Mientras tanto, el control vuelve al llamador de SumPageSizesAsync. Cuando getContentsTask haya finalizado, la expresión Await se evalúa como una 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 obtener el ejemplo completo, vea Walkthrough: Accessing the Web by Using Async and Await (Tutorial: Acceso a la web usando Async y Await). Puede descargar el ejemplo desde el explorador de ejemplos de .NET. El código de ejemplo está en el proyecto SerialAsyncExample.

Si Await se aplica al resultado de una llamada al método que devuelve Task(Of TResult), el tipo de la expresión Await será TResult. Si Await se aplica al resultado de una llamada al método que devuelve Task, la expresión Await no devuelve un valor. En el siguiente ejemplo se ilustra la diferencia.

' 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()

Una expresión o instrucción Await no bloquea el subproceso en el que se ejecuta. En su lugar, hace que el compilador suscriba el resto del método asincrónico, después de la expresión Await, como una continuación de la tarea esperada. A continuación, el control vuelve al llamador del método asincrónico. Cuando la tarea se completa, invoca su continuación y la ejecución del método asincrónico se reanuda donde se quedó.

Una expresión Await solo puede aparecer en el cuerpo de un método envolvente inmediato o una expresión lambda marcados con el modificador Async. El término Await solo sirve como palabra clave en ese contexto. En cualquier otra parte, se interpretará como identificador. Dentro del método Async o la expresión lambda, una expresión Await no puede aparecer en una expresión de consulta, en el bloque Catch o Finally de una instrucción Try…Catch…Finally, en la expresión variable de control de un bucle For o For Each, o bien en el cuerpo de una instrucción SyncLock.

Excepciones

La mayoría de los métodos asincrónicos devuelven un objeto Task o Task<TResult>. Las propiedades de la tarea devuelta llevan información acerca de su estado e historial, por ejemplo, si la tarea se ha completado, si el método asincrónico produjo una excepción o si se ha cancelado y cuál es el resultado final. El operador Await tiene acceso a esas propiedades.

Si espera un método asincrónico que devuelve una tarea y causa una excepción, el operador Await volverá a generar la excepción.

Si espera un método asincrónico que devuelve una tarea y se cancela, el operador Await volverá a generar OperationCanceledException.

Una única tarea en estado de error puede reflejar varias excepciones. Por ejemplo, la tarea podría ser el resultado de una llamada a Task.WhenAll. Cuando espera dicha tarea, la operación await vuelve a generar únicamente una de las excepciones. Sin embargo, no se puede predecir cuál de las excepciones se vuelve a generar.

Para ejemplos de control de errores en métodos asincrónicos, consulte Instrucción Try…Catch…Finally.

Ejemplo

El ejemplo siguiente de Windows Forms muestra el uso de Await en un método asincrónico, WaitAsynchronouslyAsync. Compare el comportamiento de dicho método con el de WaitSynchronously. Sin un operador Await, WaitSynchronously se ejecuta sincrónicamente a pesar del uso del modificador Async en su definición y una llamada a Thread.Sleep en el cuerpo.

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

Consulte también