Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Vous pouvez éviter les goulots d’étranglement des performances et améliorer la réactivité globale de votre application à l’aide de la programmation asynchrone. Toutefois, les techniques traditionnelles d’écriture d’applications asynchrones peuvent être compliquées, ce qui les rend difficiles à écrire, déboguer et gérer.
Visual Studio 2012 a introduit une approche simplifiée, une programmation asynchrone, qui tire parti de la prise en charge asynchrone dans .NET Framework 4.5 et versions ultérieures, ainsi que dans Windows Runtime. Le compilateur effectue le travail difficile que le développeur a utilisé pour effectuer, et votre application conserve une structure logique qui ressemble à du code synchrone. Par conséquent, vous bénéficiez de tous les avantages de la programmation asynchrone avec une fraction de l’effort.
Cette rubrique fournit une vue d’ensemble du moment et de la façon d’utiliser la programmation asynchrone et inclut des liens vers des rubriques de support qui contiennent des détails et des exemples.
Async améliore la réactivité
La synchronisation est essentielle pour les activités potentiellement bloquantes, par exemple lorsque votre application accède au web. L’accès à une ressource web est parfois lent ou retardé. Si une telle activité est bloquée dans un processus synchrone, l’application entière doit attendre. Dans un processus asynchrone, l’application peut continuer avec d’autres travaux qui ne dépendent pas de la ressource web tant que la tâche potentiellement bloquante n’est pas terminée.
Le tableau suivant présente les zones typiques où la programmation asynchrone améliore la réactivité. Les API répertoriées à partir du .NET Framework 4.5 et de Windows Runtime contiennent des méthodes qui prennent en charge la programmation asynchrone.
Domaine d'application | Prise en charge des API qui contiennent des méthodes asynchrones |
---|---|
Accès web | HttpClient, SyndicationClient |
Utilisation de fichiers | StorageFile, , StreamWriterStreamReader, ,XmlReader |
Utilisation d’images | MediaCapture, BitmapEncoder, BitmapDecoder |
Programmation WCF | Opérations synchrones et asynchrones |
Asynchrony prouve particulièrement utile pour les applications qui accèdent au thread d’interface utilisateur, car toutes les activités liées à l’interface utilisateur partagent généralement un thread. Si un processus est bloqué dans une application synchrone, tous 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 de répondre à l’interface utilisateur. Vous pouvez redimensionner ou réduire une fenêtre, par exemple, ou fermer l’application si vous ne souhaitez pas attendre qu’elle se termine.
L’approche asynchrone ajoute l’équivalent d’une transmission automatique à la liste des options que vous pouvez choisir lors de la conception d’opérations asynchrones. Autrement dit, vous bénéficiez de tous les avantages de la programmation asynchrone traditionnelle, mais avec beaucoup moins d’efforts du développeur.
Les méthodes asynchrones sont plus faciles à écrire
Les mots clés Async et Await dans Visual Basic sont le cœur de la programmation asynchrone. En utilisant 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 Async
et Await
sont appelées méthodes asynchrones.
L’exemple suivant montre une méthode asynchrone. Presque tout dans le code doit vous sembler complètement familier. Les commentaires mentionnent les fonctionnalités que vous ajoutez pour créer l'asynchronie.
Vous trouverez un fichier d’exemple WPF (Windows Presentation Foundation) complet à la fin de cette rubrique, et vous pouvez télécharger l’exemple à partir d’Async Sample : Exemple de « Programmation asynchrone avec Async et Await ».
' Three things to note about writing an Async Function:
' - The function has an Async modifier.
' - Its return type is Task or Task(Of T). (See "Return Types" section.)
' - As a matter of convention, its name ends in "Async".
Async Function AccessTheWebAsync() As Task(Of Integer)
Using client As New HttpClient()
' Call and await separately.
' - AccessTheWebAsync can do other things while GetStringAsync is also running.
' - getStringTask stores the task we get from the call to GetStringAsync.
' - Task(Of String) means it is a task which returns a String when it is done.
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://learn.microsoft.com/dotnet")
' You can do other work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork()
' The Await operator suspends AccessTheWebAsync.
' - AccessTheWebAsync does not 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.
Dim urlContents As String = Await getStringTask
' The Return statement specifies an Integer result.
' A method which awaits AccessTheWebAsync receives the Length value.
Return urlContents.Length
End Using
End Function
Si AccessTheWebAsync
n'a aucun travail qu'il peut effectuer entre l'appel de GetStringAsync
et l'attente de son achèvement, vous pouvez simplifier votre code en appelant et attendant dans l'instruction unique suivante.
Dim urlContents As String = Await client.GetStringAsync()
Les caractéristiques suivantes résument ce qui rend l’exemple précédent d’une méthode asynchrone :
La signature de méthode inclut un
Async
modificateur.Le nom d’une méthode asynchrone, par convention, se termine par un suffixe « Async ».
Le type de retour est l’un des types suivants :
- Task(Of TResult) si votre méthode a une instruction return dans laquelle l’opérande a le type TResult.
- Task si votre méthode n’a pas d’instruction return ou n’a pas d’instruction return sans opérande.
- Sub si vous écrivez un gestionnaire d'événements asynchrone.
Pour plus d’informations, consultez « Types et paramètres de retour » plus loin dans cette rubrique.
La méthode inclut généralement au moins une expression await, qui marque un point où la méthode ne peut pas continuer tant que l’opération asynchrone attendue n’est pas terminée. En attendant, la méthode est suspendue et le contrôle retourne à l’appelant de la méthode. La section suivante de cette rubrique illustre ce qui se passe au point de suspension.
Dans les méthodes asynchrones, vous utilisez les mots clés et types fournis pour indiquer ce que vous souhaitez faire, et le compilateur effectue le reste, y compris suivre ce qui doit se produire lorsque le contrôle retourne à un point d’attente dans une méthode suspendue. Certains processus de routine, tels que les boucles et la gestion des exceptions, peuvent être difficiles à gérer dans le code asynchrone traditionnel. Dans une méthode asynchrone, vous écrivez ces éléments autant que vous le feriez dans une solution synchrone, et le problème est résolu.
Pour plus d’informations sur l’asynchronie dans les versions précédentes du .NET Framework, consultez TPL et Programmation asynchrone .NET Framework traditionnelle.
Que se passe-t-il dans une méthode Async
La chose la plus importante à comprendre dans la programmation asynchrone est la façon dont le flux de contrôle passe de la méthode à la méthode. Le diagramme suivant vous guide tout au long du processus :
Les nombres du diagramme correspondent aux étapes suivantes :
Un gestionnaire d’événements appelle et attend la
AccessTheWebAsync
méthode asynchrone.AccessTheWebAsync
crée une HttpClient instance et appelle la GetStringAsync méthode asynchrone pour télécharger le contenu d’un site web sous forme de chaîne.Quelque chose se produit dans
GetStringAsync
ce qui 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
donne le contrôle à son appelant.AccessTheWebAsync
GetStringAsync
retourne une tâche(Of TResult) où TResult est une chaîne etAccessTheWebAsync
affecte la tâche à lagetStringTask
variable. La tâche représente le processus en cours de l'appel deGetStringAsync
, avec l'engagement de produire une valeur de chaîne réelle lorsque le travail est terminé.Comme
getStringTask
n’a pas encore été attendu,AccessTheWebAsync
peut continuer avec d’autres travaux qui ne dépendent pas du résultat final deGetStringAsync
. Ce travail est représenté par un appel à la méthodeDoIndependentWork
synchrone.DoIndependentWork
est une méthode synchrone qui effectue son travail et retourne à son appelant.AccessTheWebAsync
n’a plus de travail à exécuter sans un résultat degetStringTask
.AccessTheWebAsync
Souhaite ensuite calculer et retourner la longueur de la chaîne téléchargée, mais la méthode ne peut pas calculer cette valeur tant que la méthode n’a pas la chaîne.Par conséquent,
AccessTheWebAsync
utilise un opérateur await pour suspendre sa progression et pour donner le contrôle à la méthode appeléeAccessTheWebAsync
.AccessTheWebAsync
retourne unTask(Of Integer)
à l’appelant. La tâche représente une promesse de produire un résultat entier qui est la longueur de la chaîne téléchargée.Remarque
Si
GetStringAsync
(et par conséquentgetStringTask
) est terminé avant queAccessTheWebAsync
ne l'attende, le contrôle reste dansAccessTheWebAsync
. Les frais de suspension et de retour àAccessTheWebAsync
seraient gaspillés si le processus asynchrone appelé (getStringTask
) est déjà terminé et AccessTheWebSync ne nécessite pas d’attendre le résultat final.À l’intérieur de l’appelant (le gestionnaire d’événements dans cet exemple), le modèle de traitement se poursuit. 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 bien il peut attendre immédiatement. Le gestionnaire d’événements attendAccessTheWebAsync
, etAccessTheWebAsync
attendGetStringAsync
.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 deGetStringAsync
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 de la 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 à partir degetStringTask
. L’instruction d’affectation affecte le résultat récupéré àurlContents
.Quand
AccessTheWebAsync
a le résultat sous forme de chaîne, la méthode peut calculer la longueur de cette chaîne. Le travail deAccessTheWebAsync
est également terminé, et ensuite le gestionnaire d’événements en attente peut reprendre. Dans l’exemple complet à la fin de la rubrique, vous pouvez confirmer que le gestionnaire d’événements récupère et imprime la valeur du résultat de longueur.
Si vous débutez avec la programmation asynchrone, prenez une minute pour prendre en compte la différence entre le comportement synchrone et 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 suspendu (étapes 3 et 6). Lorsque la méthode asynchrone termine 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 le flux de contrôle, consultez Flux de contrôle dans les programmes asynchrones (Visual Basic).
Méthodes asynchrones d’API
Vous vous demandez peut-être où trouver des méthodes telles que GetStringAsync
celles qui prennent en charge la programmation asynchrone. .NET Framework 4.5 ou version ultérieure contient de nombreux membres qui fonctionnent avec Async
et Await
. Vous pouvez reconnaître ces membres par le suffixe « Async » attaché au nom du membre et un type de retour de Task ou Task(Of TResult). Par exemple, la System.IO.Stream
classe contient des méthodes telles que CopyToAsync, ReadAsyncet WriteAsync en même temps que les méthodes CopyTosynchrones , Readet Write.
Windows Runtime contient également de nombreuses méthodes que vous pouvez utiliser avec Async
et Await
dans les applications Windows. Pour plus d’informations et d’exemples de méthodes, consultez Appeler des API asynchrones en C# ou Visual Basic, programmation asynchrone (applications Windows Runtime) et WhenAny : Pontage entre .NET Framework et Windows Runtime.
Fils de discussion
Les méthodes asynchrones sont destinées à être des opérations non bloquantes. Une Await
expression dans une méthode asynchrone ne bloque pas le thread actuel pendant l’exécution de la tâche attendue. Au lieu de cela, l'expression inscrit le reste de la méthode comme continuation et retourne le contrôle à l'appelant de la méthode async.
Les Async
mots clés et Await
ne provoquent pas la création de threads supplémentaires. Les méthodes asynchrones ne nécessitent pas de multithreading, car une méthode asynchrone ne s’exécute pas sur son propre thread. La méthode s’exécute sur le contexte de synchronisation actuel et utilise le temps sur le thread uniquement lorsque la méthode 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 n’aide pas avec un processus qui attend simplement que les résultats soient disponibles.
L’approche basée sur async pour la programmation asynchrone est préférable aux approches existantes dans la plupart des cas. En particulier, cette approche est meilleure que BackgroundWorker pour les opérations liées aux E/S, car le code est plus simple et vous n’avez pas à vous protéger contre les conditions de concurrence. En combinaison avec Task.Run, la programmation asynchrone est meilleure que BackgroundWorker pour les opérations liées au processeur, car la programmation asynchrone sépare les détails de coordination de l’exécution de votre code du travail qui Task.Run
transfère vers le threadpool.
Async et Await
Si vous spécifiez qu’une méthode est une méthode asynchrone à l’aide d’un modificateur Async , vous activez les deux fonctionnalités suivantes.
La méthode asynchrone marquée peut utiliser Await pour désigner des points de suspension. L’opérateur await indique au compilateur que la méthode asynchrone ne peut pas continuer après ce point tant que le processus asynchrone attendu n’est pas terminé. En attendant, le contrôle retourne à l’appelant de la méthode asynchrone.
La suspension d’une méthode asynchrone à une
Await
expression ne constitue pas une sortie de la méthode etFinally
les blocs ne s’exécutent pas.La méthode async marquée peut elle-même être attendue par les méthodes qui l'appellent.
Une méthode asynchrone contient généralement une ou plusieurs occurrences d’un Await
opérateur, mais l’absence d’expressions Await
ne provoque pas d’erreur du compilateur. Si une méthode asynchrone n’utilise pas d’opérateur Await
pour marquer un point de suspension, la méthode s’exécute comme une méthode synchrone, malgré le Async
modificateur. Le compilateur émet un avertissement pour ces méthodes.
Async
et Await
sont des mots clés contextuels. Pour plus d’informations et d’exemples, consultez les rubriques suivantes :
Types et paramètres de retour
Dans la programmation .NET Framework, une méthode asynchrone retourne généralement un Task ou un Task(Of TResult). À l’intérieur d’une méthode asynchrone, un opérateur Await
est appliqué à une tâche retournée par un appel à une autre méthode asynchrone.
Vous spécifiez Task(Of TResult) comme type de retour si la méthode contient une instruction Return qui spécifie un opérande de type TResult
.
Vous utilisez Task
comme type de retour si la méthode n’a pas d’instruction return ou a une instruction return qui ne retourne pas d’opérande.
L’exemple suivant montre comment déclarer et appeler une méthode qui retourne une tâche(of TResult) ou un Task:
' Signature specifies Task(Of Integer)
Async Function TaskOfTResult_MethodAsync() As Task(Of Integer)
Dim hours As Integer
' . . .
' Return statement specifies an integer result.
Return hours
End Function
' Calls to TaskOfTResult_MethodAsync
Dim returnedTaskTResult As Task(Of Integer) = TaskOfTResult_MethodAsync()
Dim intResult As Integer = Await returnedTaskTResult
' or, in a single statement
Dim intResult As Integer = Await TaskOfTResult_MethodAsync()
' Signature specifies Task
Async Function Task_MethodAsync() As Task
' . . .
' The method has no return statement.
End Function
' 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 asynchrone peut également être une Sub
méthode. Ce type de retour est utilisé principalement pour définir des gestionnaires d’événements, où un type de retour est requis. Les gestionnaires d’événements asynchrones servent souvent de point de départ pour les programmes asynchrones.
Une méthode async qui est une procédure Sub
ne peut pas être attendue, et l’appelant ne peut capturer aucune exception levée par la méthode.
Une méthode asynchrone ne peut pas déclarer de paramètres ByRef , mais la méthode peut appeler des méthodes qui ont de tels paramètres.
Pour plus d’informations et d’exemples, consultez Types de retour asynchrones (Visual Basic). Pour plus d’informations sur la façon d’intercepter des exceptions dans des méthodes asynchrones, consultez Try...Catch...Finally Statement.
Les API asynchrones de la programmation Windows Runtime ont l’un des types de retour suivants, qui sont similaires aux tâches :
- IAsyncOperation(Of TResult), qui correspond à Task(Of TResult)
- IAsyncAction, qui correspond à Task
- IAsyncActionWithProgress(Of TProgress)
- IAsyncOperationWithProgress(Of TResult, TProgress)
Pour plus d’informations et un exemple, consultez Appeler des API asynchrones en C# ou Visual Basic.
Conventions d’affectation de noms
Par convention, vous ajoutez « Async » aux noms des méthodes qui ont un Async
modificateur.
Vous pouvez ignorer la convention dans laquelle un événement, une classe de base ou un contrat d’interface suggère un autre nom. Par exemple, vous ne devez pas renommer les gestionnaires d’événements courants, tels que Button1_Click
.
Rubriques et exemples connexes (Visual Studio)
Exemple complet
Le code suivant est le fichier MainWindow.xaml.vb de l’application WPF (Windows Presentation Foundation) que cette rubrique traite. Vous pouvez télécharger l’exemple à partir de l’exemple Async : exemple à partir de « Programmation asynchrone avec Async et Await ».
Imports System.Net.Http
' Example that demonstrates Asynchronous Programming with Async and Await.
' It uses HttpClient.GetStringAsync to download the contents of a website.
' Sample Output:
' Working . . . . . . .
'
' Length of the downloaded string: 39678.
Class MainWindow
' Mark the event handler with Async so you can use Await in it.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' Call and await immediately.
' StartButton_Click suspends until AccessTheWebAsync is done.
Dim contentLength As Integer = Await AccessTheWebAsync()
ResultsTextBox.Text &= $"{vbCrLf}Length of the downloaded string: {contentLength}.{vbCrLf}"
End Sub
' Three things to note about writing an Async Function:
' - The function has an Async modifier.
' - Its return type is Task or Task(Of T). (See "Return Types" section.)
' - As a matter of convention, its name ends in "Async".
Async Function AccessTheWebAsync() As Task(Of Integer)
Using client As New HttpClient()
' Call and await separately.
' - AccessTheWebAsync can do other things while GetStringAsync is also running.
' - getStringTask stores the task we get from the call to GetStringAsync.
' - Task(Of String) means it is a task which returns a String when it is done.
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://learn.microsoft.com/dotnet")
' You can do other work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork()
' The Await operator suspends AccessTheWebAsync.
' - AccessTheWebAsync does not 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.
Dim urlContents As String = Await getStringTask
' The Return statement specifies an Integer result.
' A method which awaits AccessTheWebAsync receives the Length value.
Return urlContents.Length
End Using
End Function
Sub DoIndependentWork()
ResultsTextBox.Text &= $"Working . . . . . . .{vbCrLf}"
End Sub
End Class