opérateur await : attend de façon asynchrone la fin d’une tâche

L’opérateur await suspend l’évaluation de la méthode async englobante jusqu’à ce que l’opération asynchrone représentée par son opérande se termine. Une fois l’opération asynchrone terminée, l’opérateur await retourne le résultat de l’opération, le cas échéant. Quand l’opérateur await est appliqué à l’opérande qui représente une opération déjà terminée, il retourne immédiatement le résultat de l’opération sans suspendre la méthode englobante. L’opérateur await ne bloque pas le thread qui évalue la méthode async. Quand l’opérateur await suspend la méthode englobante, le contrôle retourne à l’appelant de la méthode.

Dans l’exemple suivant, la méthode HttpClient.GetByteArrayAsync retourne l’instance Task<byte[]>, qui représente une opération asynchrone qui produit un tableau d’octets au moment où elle se termine. Tant que l’opération n’est pas terminée, l’opérateur await suspend la méthode DownloadDocsMainPageAsync. Quand la méthode DownloadDocsMainPageAsync est suspendue, le contrôle est retourné à la méthode Main, qui est l’appelant de DownloadDocsMainPageAsync. La méthode Main s’exécute jusqu’à ce qu’elle ait besoin du résultat de l’opération asynchrone effectuée par la méthode DownloadDocsMainPageAsync. Une fois que tous les octets ont été obtenus par GetByteArrayAsync, le reste de la méthode DownloadDocsMainPageAsync est évalué. Après cela, le reste de la méthode Main est évalué.

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.

L’opérande d’une expression await doit fournir une notification lorsqu’une tâche se termine. En général, un délégué est appelé lorsque la tâche se termine, que ce soit une réussite ou un échec. La section await de la spécification du langage C# fournit les détails sur la façon dont ces notifications sont implémentées.

L’exemple précédent utilise la méthode méthode Main asynchrone. Pour plus d’informations, consultez la section Opérateur await dans la méthode Main.

Notes

Pour obtenir une introduction à la programmation asynchrone, consultez Programmation asynchrone avec async et await. La programmation asynchrone avec async et await suit le modèle asynchrone basé sur les tâches.

Vous pouvez utiliser l’opérateur await uniquement dans une méthode, une expression lambda ou une méthode anonyme modifiée par le mot clé async. Dans une méthode asynchrone, vous ne pouvez pas utiliser l’opérateur await dans le corps d’une fonction synchrone, à l’intérieur du bloc d’une instruction lock et dans un contexte unsafe.

L’opérande de l’opérateur await est généralement un des types .NET suivants : Task, Task<TResult>, ValueTask ou ValueTask<TResult>. Cependant, n’importe quelle expression awaitable peut être l’opérande de l’opérateur await. Pour plus d’informations, consultez la section Expressions awaitable de la spécification du langage C#.

Le type d’expression await t est TResult si le type d’expression t est Task<TResult> ou ValueTask<TResult>. Si le type de t est Task ou ValueTask, le type de await t est void. Dans les deux cas, si t lève une exception, await t lève à nouveau l’exception.

Flux asynchrones et éléments jetables

Vous utilisez l’instruction await foreach pour consommer un flux asynchrone de données. Pour plus d’informations, consultez la section foreach de l’article Instructions d’itération.

Vous utilisez l’instruction await using pour utiliser un objet jetable de façon asynchrone. Autrement dit un objet d’un type qui implémente une interface IAsyncDisposable. Pour plus d’informations, consultez la section Utilisation d’objet jetable asynchrone de l’article Implémenter une méthode DisposeAsync.

Opérateur await dans la méthode Main

La méthode Main, qui est le point d’entrée de l’application, peut retourner Task ou Task<int>, ce qui lui permet d’être asynchrone. Vous pouvez ainsi utiliser l’opérateur await dans son corps. Dans les versions antérieures de C#, pour être certain que la méthode Main attend la fin d’une opération asynchrone, vous pouvez récupérer la valeur de la propriété Task<TResult>.Result de l’instance Task<TResult> retournée par la méthode asyn correspondante. Pour les opérations asynchrones qui ne produisent pas de valeur, vous pouvez appeler la méthode Task.Wait. Pour savoir comment sélectionner la version du langage, voir Contrôle de version du langage C#.

spécification du langage C#

Pour plus d’informations, consultez la section Expressions await de la spécification du langage C#.

Voir aussi