Compartir a través de


Operador await: espera asincrónicamente para que se complete una tarea

El operador await suspende la evaluación del método async envolvente hasta que se completa la operación asincrónica representada por su operando. Cuando se completa la operación asincrónica, el operador await devuelve el resultado de la operación, si existe. Cuando el operador await se aplica al operando que representa una operación ya completada, devuelve el resultado de la operación inmediatamente sin suspender el método envolvente. El operador await no bloquea el subproceso que evalúa el método async. Cuando el operador await suspende el método async envolvente, el control vuelve al autor de la llamada del método.

La documentación de referencia del lenguaje C# cubre la versión más reciente publicada del lenguaje C#. También contiene documentación inicial sobre las características de las versiones preliminares públicas de la próxima versión del lenguaje.

La documentación identifica cualquier característica introducida por primera vez en las últimas tres versiones del idioma o en las versiones preliminares públicas actuales.

Sugerencia

Para buscar cuándo se introdujo por primera vez una característica en C#, consulte el artículo sobre el historial de versiones del lenguaje C#.

En el ejemplo siguiente, el método HttpClient.GetByteArrayAsync devuelve la instancia Task<byte[]>, que representa una operación asincrónica que genera una matriz de bytes cuando se completa. Hasta que se complete la operación, el operador await suspende el método DownloadDocsMainPageAsync. Cuando se suspende DownloadDocsMainPageAsync, se devuelve el control Main al método, que es el autor de la llamada a DownloadDocsMainPageAsync. El método Main se ejecuta hasta que necesita el resultado de la operación asincrónica realizada por el método DownloadDocsMainPageAsync. Cuando GetByteArrayAsync obtiene todos los bytes, se evalúa el resto del método DownloadDocsMainPageAsync. Después, se evalúa el resto del método Main.

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.

El operando de una expresión await debe proporcionar notificaciones cuando se complete una tarea. En general, se invoca un delegado cuando se completa la tarea, ya sea correctamente o sin éxito. La sección await de la especificación del lenguaje C# proporciona los detalles sobre cómo se implementan estas notificaciones.

En el ejemplo anterior se usa el método Main asincrónico. Para obtener más información, vea la sección Operador await en el método Main.

Nota:

Para obtener una introducción a la programación asincrónica, vea Programación asincrónica con async y await. La programación asincrónica con async y await sigue el modelo asincrónico basado en tareas.

El operador await se puede usar solamente en un método, una expresión lambda o un método anónimo modificado por la palabra clave async. Dentro de un método asincrónico, no se puede usar el operador await en el cuerpo de una función sincrónica, dentro del bloque de una instrucción lock y en un contexto no seguro.

El operando del operador await suele ser de uno de los siguientes tipos de .NET: Task, Task<TResult>, ValueTask o ValueTask<TResult>. Aunque cualquier expresión con await puede ser el operando del operador await. Para obtener más información, vea la sección Expresiones con await de la especificación del lenguaje C#.

El tipo de expresión await t es TResult si el tipo de expresión t es Task<TResult> o ValueTask<TResult>. Si el tipo de t es Task o ValueTask, el tipo de await t es void. En ambos casos, si t produce una excepción, await t vuelve a producir la excepción.

Flujos asincrónicos y descartables

Se usa la instrucción await foreach para consumir un flujo de datos asincrónico. Para obtener más información, consulte la sección instrucciones foreach del artículo Instrucciones de iteración.

Se usa la instrucción await using para trabajar con un objeto descartable de forma asincrónica, es decir, un objeto de un tipo que implementa una interfaz IAsyncDisposable. Para obtener más información, vea la sección Uso de la eliminación asincrónica del artículo Implementación de un método DisposeAsync.

Operador await en el método Main

El Main método actúa como punto de entrada de la aplicación. Puede devolver Task o Task<int>, lo que lo convierte en asincrónico. Al crear el Main método asincrónico, puede usar el await operador en su cuerpo. En versiones anteriores de C#, para asegurarse de que el Main método espera la finalización de una operación asincrónica, recupere el valor de la Task<TResult>.Result propiedad de la Task<TResult> instancia que devuelve el método asincrónico correspondiente. Para las operaciones asincrónicas que no generan un valor, llame al Task.Wait método . Para obtener información sobre cómo seleccionar la versión del lenguaje, vea Control de versiones del lenguaje C#.

Especificación del lenguaje C#

Para obtener más información, vea la sección Expresiones await de la especificación del lenguaje C#.

Consulte también