Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction manuelle. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source

Programmation asynchrone avec Async et Await (C# et Visual Basic)

Vous pouvez éviter des goulots d'étranglement au niveau des performances et améliorer la réactivité globale de votre application à l'aide de la programmation asynchrone. Toutefois, les techniques traditionnelles pour écrire des applications asynchrones peuvent être complexes et rendre ces applications difficiles à écrire, déboguer et mettre à jour.

Visual Studio 2012 présente une approche simplifiée, la programmation async, qui tire parti de la prise en charge asynchrone dans .NET Framework 4.5 et Windows Runtime. Le compilateur effectue le travail difficile que le développeur avait l'habitude de faire, et votre application conserve une structure logique qui ressemble au code synchrone. Par conséquent, vous obtenez tous les avantages de la programmation asynchrone avec peu d'effort.

Cette rubrique comprend les sections suivantes.

Cette rubrique fournit une vue d'ensemble sur quand et comment utiliser la programmation asynchrone, et inclut des liens vers des rubriques du support, qui contiennent des informations et des exemples.

La programmation asynchrone est essentielle pour les activités qui sont potentiellement bloquantes, comme par exemple lorsque votre application accède au Web. L'accès à une ressource Web est parfois lent ou différé. Si cette activité est bloquée dans un processus synchrone, l'application entière doit attendre. Dans un processus asynchrone, l'application peut continuer avec un autre travail qui ne dépend pas de la ressource Web jusqu'à ce que la tâche potentiellement bloquante soit terminée.

Le tableau suivant indique les zones classiques où la programmation asynchrone améliore la réactivité. Les API répertoriées de .NET Framework 4,5 et de Windows Runtime contiennent des méthodes qui prennent en charge la programmation asynchrone.

Domaine d'application

API de prise en charge qui contiennent des méthodes async

Accès Web

HttpClient , SyndicationClient

Utilisation de fichiers

StorageFile, StreamWriter, StreamReader, XmlReader

Utilisation d'images

MediaCapture, BitmapEncoder, BitmapDecoder

Programmation WCF

Opérations synchrones et asynchrones

Le comportement asynchrone est particulièrement utile pour les applications qui accèdent au thread d'interface utilisateur, car toute activité liée à l'interface utilisateur partage généralement un thread. Si un processus est bloqué dans une application synchrone, tous les processus sont bloqués. Votre application ne répond plus et vous pouvez conclure qu'elle a rencontré une défaillance, alors qu'elle attend simplement.

Lorsque vous utilisez des méthodes asynchrones, l'application continue à répondre à l'interface utilisateur. Vous pouvez redimensionner ou réduire une fenêtre, par exemple, ou vous pouvez fermer l'application si vous ne souhaitez pas attendre qu'elle se termine.

L'approche basée sur async ajoute l'équivalent d'une transmission automatique à la liste d'options dont vous disposez pour concevoir des opérations asynchrones. En d'autres termes, vous obtenez tous les avantages de la programmation asynchrone classique mais avec beaucoup moins d'efforts de la part du développeur.

Les mots clés Async et Await (Attendez) en Visual Basic et les mots clés async et await (attendez) en C# sont le cœur de la programmation asynchrone. Avec ces deux mots clés, vous pouvez utiliser des ressources dans .NET Framework ou Windows Runtime pour créer une méthode asynchrone presque aussi facilement que vous créez une méthode synchrone. Les méthodes asynchrones que vous définissez à l'aide d'async et await sont appelées des méthodes async.

L'exemple suivant illustre une méthode async. Presque tous les éléments du code doivent vous sembler familiers. Les commentaires indiquent les fonctionnalités que vous ajoutez pour créer le comportement asynchrone.

Vous trouverez le fichier d'exemple complet à la fin de cette rubrique et vous pouvez télécharger l'exemple depuis Exemple async : exemple de programmation asynchrone avec async et await .


// Three things to note in the signature:
//  - The method has an async modifier. 
//  - The return type is Task or Task<T>. (See "Return Types" section.)
//    Here, it is Task<int> because the return statement returns an integer.
//  - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();

    // GetStringAsync returns a Task<string>. That means that when you await the
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();

    // The await operator suspends AccessTheWebAsync.
    //  - AccessTheWebAsync can't continue until getStringTask is complete.
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync.
    //  - Control resumes here when getStringTask is complete. 
    //  - The await operator then retrieves the string result from getStringTask.
    string urlContents = await getStringTask;

    // The return statement specifies an integer result.
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
    return urlContents.Length;
}


Si AccessTheWebAsync n'a aucun travail à faire entre l'appel de GetStringAsync et l'attente de son achèvement, vous pouvez simplifier votre code en appelant et en attendant dans l'instruction unique suivante.

string urlContents = await client.GetStringAsync();

Les caractéristiques suivantes résument ce qui fait de l'exemple précédent une méthode async.

  • La signature de la méthode inclut un modificateur Async ou async.

  • Le nom d'une méthode async, par convention, se termine par un suffixe « Async ».

  • Le type de retour est l'un des types suivants :

    • Task<TResult> si votre méthode a une instruction de retour dans laquelle l'opérande a le type TResult.

    • Task si votre méthode n'a aucune instruction de retour, ou si elle a une instruction de retour sans opérande.

    • Void (Sub en Visual Basic) si vous écrivez un gestionnaire d'événements async.

    Pour plus d'informations, consultez « Types et paramètres de retour » dans la suite de cette rubrique.

  • La méthode inclut généralement au moins une expression await, qui marque le point au-delà duquel la méthode ne peut pas poursuivre son exécution tant que l'opération asynchrone attendue n'est pas terminée. Dans le même temps, la méthode est interrompue, et le contrôle retourne à l'appelant de la méthode. La section suivante de cette rubrique illustre ce qui se produit au point d'interruption.

Dans les méthodes async, vous utilisez les mots clés et les types fournis pour indiquer ce que vous souhaitez faire, et le compilateur effectue le reste, notamment le suivi de ce qui doit se produire lorsque le contrôle retourne à un point d'attente dans une méthode interrompue. Il peut être difficile de gérer des processus de routine, tels que les boucles et la gestion des exceptions, dans le code asynchrone traditionnel. Dans une méthode async, vous écrivez ces éléments comme vous l'auriez fait dans une solution synchrone, et le problème est résolu.

Pour plus d'informations sur le comportement asynchrone dans les versions précédentes du .NET Framework, consultez Bibliothèque parallèle de tâches (TPL) et programmation asynchrone .NET Framework.

La chose la plus importante à comprendre dans la programmation asynchrone est comment le flux de contrôle se déplace d'une méthode à l'autre. Le diagramme suivant vous guide dans le processus.

Suivre un programme async

Les numéros du diagramme correspondent aux étapes suivantes.

  1. Un gestionnaire d'événements appelle et attend la méthode async AccessTheWebAsync.

  2. AccessTheWebAsync crée une instance HttpClient et appelle la méthode asynchrone GetStringAsync pour télécharger le contenu d'un site Web comme une chaîne.

  3. Quelque chose se produit dans GetStringAsync et suspend sa progression. Elle peut être obligée d'attendre la fin d'un téléchargement sur un site Web ou de toute autre activité bloquante. Pour éviter de bloquer les ressources, GetStringAsync cède le contrôle à son appelant, AccessTheWebAsync.

    GetStringAsync retourne un Task<TResult> où TResult est une chaîne et AccessTheWebAsync assigne la tâche à la variable getStringTask. La tâche représente le processus en cours de l'appel de GetStringAsync, avec l'engagement de produire une valeur de chaîne réelle lorsque le travail est terminé.

  4. Étant donné que getStringTask n'a pas encore été attendu, AccessTheWebAsync peut continuer avec un autre travail qui ne dépend pas du résultat final issu de GetStringAsync. Cette opération est représentée par un appel à la méthode synchrone DoIndependentWork.

  5. DoIndependentWork est une méthode synchrone qui effectue son travail et retourne à son appelant.

  6. AccessTheWebAsync n'a plus de travail à exécuter sans un résultat de getStringTask. AccessTheWebAsync veut ensuite calculer et retourner la longueur de la chaîne téléchargée, mais la méthode ne peut pas calculer cette valeur avant d'avoir la chaîne.

    Par conséquent, AccessTheWebAsync utilise un opérateur await pour interrompre sa progression et pour céder le contrôle à la méthode ayant appelé AccessTheWebAsync. AccessTheWebAsync retourne Task(Of Integer) ou Task<int> à l'appelant. La tâche représente la promesse de produire un résultat entier qui est la longueur de la chaîne téléchargée.

    Remarque Remarque

    Si GetStringAsync (et donc getStringTask) est terminé avant que AccessTheWebAsync ne l'attende, le contrôle reste dans AccessTheWebAsync. Le fait de suspendre, puis de retourner à AccessTheWebAsync ne sert à rien si le processus asynchrone appelé (getStringTask) s'est déjà effectué et si AccessTheWebSync n'a pas à attendre le résultat final.

    Dans l'appelant (le gestionnaire d'événements dans cet exemple), le modèle de traitement continue. L'appelant peut effectuer d'autres tâches qui ne dépendent pas du résultat de AccessTheWebAsync avant d'attendre ce résultat, ou l'appelant peut attendre immédiatement. Le gestionnaire d'événements attend AccessTheWebAsync, et AccessTheWebAsync attend GetStringAsync.

  7. GetStringAsync se termine et génère un résultat de chaîne. Le résultat de chaîne n'est pas retourné par l'appel de GetStringAsync de la façon à laquelle vous pourriez vous attendre. (N'oubliez pas que la méthode a déjà retourné une tâche à l'étape 3.) Au lieu de cela, le résultat chaîne est stocké dans la tâche qui représente l'achèvement de la méthode, getStringTask. L'opérateur await récupère le résultat de getStringTask. L'instruction d'assignation assigne le résultat récupéré à urlContents.

  8. Lorsque AccessTheWebAsync a le résultat de chaîne, la méthode peut calculer la longueur de la chaîne. Puis, le travail d'AccessTheWebAsync est également interrompu, et le gestionnaire d'événements en attente peut reprendre. Dans l'exemple complet à la fin de la rubrique, vous pouvez vérifier que le gestionnaire d'événements récupère et imprime la valeur du résultat de la longueur.

Si vous débutez en programmation asynchrone, prenez une minute pour déterminer la différence entre le comportement synchrone et le comportement asynchrone. Une méthode synchrone retourne une fois son travail terminé (étape 5), mais une méthode asynchrone retourne une valeur de tâche lorsque son travail est interrompu (étapes 3 et 6). Lorsque la méthode async termine finalement son travail, la tâche est marquée comme terminée et le résultat, le cas échéant, est stocké dans la tâche.

Pour plus d'informations sur les flux de contrôle, consultez Flux de contrôle dans les programmes Async (C# et Visual Basic).

Vous pouvez vous demander où rechercher les méthodes telles que GetStringAsync qui prennent en charge la programmation async. Le .NET Framework 4.5 contient plusieurs membres qui utilisent async et await. Vous pouvez identifier ces membres par le suffixe « Async » joint au nom de membre et un type de retour Task ou Task<TResult>. Par exemple, la classe System.IO.Stream contient des méthodes telles que CopyToAsync, ReadAsync, et WriteAsync à côté des méthodes synchrones CopyTo, Read, et Write.

Windows Runtime contient également de nombreuses méthodes que vous pouvez utiliser avec async et await dans les applications Windows Store. Pour plus d'informations et pour découvrir des exemples de méthodes, consultez Démarrage rapide : utilisation de l'opérateur await pour la programmation asynchrone, Programmation asynchrone (applications Windows Store) et WhenAny : combler l'écart entre .NET Framework et Windows Runtime (C# et Visual Basic).

Les méthodes Async sont conçues pour être des opérations non bloquantes. Une expression await dans une méthode async ne bloque pas le thread actuel pendant que la tâche attendue s'exécute. Au lieu de cela, l'expression inscrit le reste de la méthode comme continuation et rend le contrôle à l'appelant de la méthode async.

Les mots clés async et await ne provoquent pas la création de threads supplémentaires. Les méthodes Async ne requièrent pas de multithreading, car une méthode async ne fonctionne pas sur son propre thread. La méthode s'exécute sur le contexte de synchronisation actuel et utilise du temps sur le thread uniquement lorsqu'elle est active. Vous pouvez utiliser Task.Run pour déplacer le travail lié au processeur vers un thread d'arrière-plan, mais un thread d'arrière-plan ne permet pas à un processus qui attend simplement les résultats de devenir disponible.

L'approche de la programmation asynchrone basée sur async est préférable aux approches existantes dans presque chaque cas. En particulier, cette approche est préférable à BackgroundWorker pour les opérations gourmandes en E/S, car le code est plus simple et il est inutile de vous protéger contre des conditions de concurrence critique. Combinée à Task.Run, la programmation asynchrone est meilleure que BackgroundWorker pour les opérations utilisant le processeur de manière intensive car la programmation asynchrone sépare les détails de coordination de l'exécution de votre code à partir du travail que Task.Run transfère au pool de threads.

Si vous spécifiez qu'une méthode est une méthode async en utilisant un modificateur Async ou async, vous activez les deux fonctionnalités suivantes.

  • La méthode marquée async peut utiliser Await ou await pour indiquer des points d'interruption. L'opérateur await indique au compilateur que la méthode async ne peut pas continuer au-delà de ce point, tant que le processus asynchrone attendu n'est pas terminé. Entre-temps, le contrôle retourne à l'appelant de la méthode async.

    L'interruption d'une méthode async dans une expression Await ne constitue pas une sortie de la méthode et les blocs finally ne s'exécutent pas.

  • La méthode async marquée peut elle-même être attendue par les méthodes qui l'appellent.

La méthode async contient généralement un ou plusieurs occurrences d'un opérateur await, mais l'absence des expressions Await ne provoque pas d'erreur du compilateur. Si une méthode async n'utilise pas un opérateur d'attente pour marquer un point de sélection, elle s'exécute comme le fait une méthode synchrone, en dépit du modificateur async. Le compilateur émet un avertissement pour ces méthodes.

Async , async, Await et await sont des mots clés contextuels. Pour plus d'informations et des exemples, consultez les rubriques suivantes :

Dans la programmation .NET Framework, une méthode async retourne généralement un Task ou Task<TResult>. Dans une méthode async, un opérateur await est appliqué à une tâche retournée à partir d'un appel à une autre méthode async.

Vous spécifiez Task<TResult> comme type de retour si la méthode contient une instruction Return (Visual Basic) ou return (C#) qui spécifie un opérande de type TResult.

Vous utilisez Task comme type de retour si la méthode n'a aucune instruction return ou une instruction return qui ne retourne pas d'opérande.

L'exemple suivant montre comment déclarer et appeler une méthode qui retourne Task<TResult> ou Task.

// Signature specifies Task<TResult>
async Task<int> TaskOfTResult_MethodAsync()
{
    int hours;
    // . . .
    // Return statement specifies an integer result.
    return hours;
}

// Calls to TaskOfTResult_MethodAsync
Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
int intResult = await returnedTaskTResult;
// or, in a single statement
int intResult = await TaskOfTResult_MethodAsync();


// Signature specifies Task
async Task Task_MethodAsync()
{
    // . . .
    // The method has no return statement.  
}

// Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync();
await returnedTask;
// or, in a single statement
await Task_MethodAsync();

Chaque tâche retournée représente le travail en cours. Une tâche encapsule des informations sur l'état du processus asynchrone et, éventuellement, le résultat final du processus ou l'exception que le processus déclenche s'il ne réussit pas.

Une méthode async peut également être une méthode Sub (Visual Basic) ou avoir un type de retour void (C#). Ce type de retour est essentiellement utilisé pour définir les gestionnaires d'événements, où un type de retour void est obligatoire. Les gestionnaires d'événements asynchrones servent souvent de point de départ aux programmes asynchrones.

Une méthode async, qui est une procédure Sub ou dont le type de retour est void, ne peut pas être attendue, et l'appellant d'une méthode void ne peut intercepter aucune exception lancée par la méthode.

Une méthode async ne peut pas déclarer des paramètres ByRef dans Visual Basic, ou des paramètres ref ou out en C#, mais la méthode peut appeler les méthodes qui ont ces paramètres.

Pour plus d'informations et d'exemples, consultez Types de retour Async (C# et Visual Basic). Pour plus d'informations sur l'interception des exceptions dans les méthodes async, consultez try-catch (référence C#) ou Try...Catch...Finally, instruction (Visual Basic).

Les API asynchrones dans la programmation Windows Runtime ont l'un des types de retour suivants, qui sont semblables aux tâches :

Pour plus d'informations et pour découvrir un exemple, consultez Démarrage rapide : utilisation de l'opérateur await pour la programmation asynchrone.

Par convention, vous ajoutez « Async » aux noms des méthodes qui possèdent un modificateur Async ou async.

Vous pouvez ignorer la convention où un événement, une classe de base, ou un contrat d'interface suggère un nom différent. Par exemple, vous ne devez pas renommer les gestionnaires d'événements communs, tels que Button1_Click.

Title

Description

Exemple

Procédure pas à pas : accès au Web avec Async et Await (C# et Visual Basic)

Montre comment convertir une solution WPF synchrone en une solution WPF asynchrone. L'application télécharge une série de sites Web.

Exemple Async : Accès à la procédure Web (C# et Visual Basic)

Comment : étendre la procédure pas à pas Async à l'aide de Task.WhenAll (C# et Visual Basic)

Ajoute Task.WhenAll à la procédure précédente. L'utilisation de WhenAll démarre tous les téléchargements en même temps.

Comment : effectuer plusieurs requêtes Web en parallèle en utilisant Async et Await (C# et Visual Basic)

Explique comment démarrer plusieurs tâches en même temps.

Exemple Async : Réalisation de plusieurs requêtes Web en parallèle (C# et Visual Basic)

Types de retour Async (C# et Visual Basic)

Décrit les types que les méthodes async peuvent retourner et explique quand chaque type est approprié.

Flux de contrôle dans les programmes Async (C# et Visual Basic)

Effectue le suivi en détail du flux de contrôle via une série d'expressions await dans un programme asynchrone.

Exemple Async : Flux de contrôle dans les programmes Async (C# et Visual Basic)

Réglage de votre application Async (C# et Visual Basic)

Indique comment ajouter les fonctionnalités suivantes à votre solution async :

Exemple Async : Ajustement de votre application (C# et Visual Basic)

Gestion de la réentrance dans Async Apps (C# et Visual Basic)

Montre comment traiter les cas où une opération asynchrone active redémarre pendant son exécution.

WhenAny : combler l'écart entre .NET Framework et Windows Runtime (C# et Visual Basic)

Montre comment établir un pont entre les types de tâche du .NET Framework et IAsyncOperations dans Windows Runtime pour pouvoir utiliser WhenAny avec une méthode Windows Runtime.

Exemple Async : Transition entre .NET et Windows Runtime (AsTask et WhenAny)

Annulation Asynch : combler l'écart entre .NET Framework et Windows Runtime (C# et Visual Basic)

Montre comment établir un pont entre les types de tâche du .NET Framework et IAsyncOperations dans Windows Runtime pour pouvoir utiliser CancellationTokenSource avec une méthode Windows Runtime.

Exemple Async : Transition entre .NET et Windows Runtime (AsTask & Annulation)

Utiliser Async pour l'accès aux fichiers (C# et Visual Basic)

Répertorie et explique les avantages de l'utilisation d'async et d'await pour accéder aux fichiers.

Procédure pas à pas : utilisation du débogueur avec les méthodes Async

Explique le flux de contrôle à une instruction Await, et explique le comportement des commandes Pas à pas détaillé, Pas à pas principal et Pas à pas sortant dans les méthodes async.

Modèle asynchrone basé sur les tâches (TAP, Task-based Asynchronous Pattern)

Décrit un nouveau modèle pour le comportement asynchrone dans le .NET Framework. Le modèle est basé sur les types Task et Task<TResult>.

Démarrage rapide : appel d'API asynchrones en C# ou Visual Basic

Indique comment utiliser async et await dans une application Windows Store.

Programmation asynchrone (applications Windows Store)

Fournit une vue d'ensemble de la programmation asynchrone dans le Windows Runtime.

Vidéos Async sur Channel 9

Fournit des liens vers diverses vidéos sur la programmation asynchrone.

Le code suivant est le fichier MainWindow.xaml.vb ou MainWindow.xaml.cs de l'application WPF (Windows Presentation Foundation) traitée dans cette rubrique. Vous pouvez télécharger l'exemple à partir de Exemple async : exemple de programmation asynchrone avec async et await.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// Add a using directive and a reference for System.Net.Http;
using System.Net.Http;

namespace AsyncFirstExample
{
    public partial class MainWindow : Window
    {
        // Mark the event handler with async so you can use await in it.
        private async void StartButton_Click(object sender, RoutedEventArgs e)
        {
            // Call and await separately.
            //Task<int> getLengthTask = AccessTheWebAsync();
            //// You can do independent work here.
            //int contentLength = await getLengthTask;

            int contentLength = await AccessTheWebAsync();

            resultsTextBox.Text +=
                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
        }


        // Three things to note in the signature:
        //  - The method has an async modifier. 
        //  - The return type is Task or Task<T>. (See "Return Types" section.)
        //    Here, it is Task<int> because the return statement returns an integer.
        //  - The method name ends in "Async."
        async Task<int> AccessTheWebAsync()
        { 
            // You need to add a reference to System.Net.Http to declare client.
            HttpClient client = new HttpClient();

            // GetStringAsync returns a Task<string>. That means that when you await the
            // task you'll get a string (urlContents).
            Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

            // You can do work here that doesn't rely on the string from GetStringAsync.
            DoIndependentWork();

            // The await operator suspends AccessTheWebAsync.
            //  - AccessTheWebAsync can't continue until getStringTask is complete.
            //  - Meanwhile, control returns to the caller of AccessTheWebAsync.
            //  - Control resumes here when getStringTask is complete. 
            //  - The await operator then retrieves the string result from getStringTask.
            string urlContents = await getStringTask;

            // The return statement specifies an integer result.
            // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
            return urlContents.Length;
        }


        void DoIndependentWork()
        {
            resultsTextBox.Text += "Working . . . . . . .\r\n";
        }
    }
}

// Sample Output:

// Working . . . . . . .

// Length of the downloaded string: 41564.


Ajouts de la communauté

AJOUTER
Afficher:
© 2015 Microsoft