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.
Les applications qui effectuent plusieurs tâches simultanément, mais qui restent réactives à l’interaction utilisateur, nécessitent souvent une conception qui utilise plusieurs threads. L’espace System.Threading de noms fournit tous les outils nécessaires pour créer des applications multithreads hautes performances, mais l’utilisation de ces outils nécessite effectivement une expérience significative avec l’ingénierie logicielle multithread. Pour les applications multithread relativement simples, le BackgroundWorker composant fournit une solution simple. Pour les applications asynchrones plus sophistiquées, envisagez d’implémenter une classe qui respecte le modèle asynchrone basé sur les événements.
Le modèle asynchrone basé sur les événements rend disponibles les avantages des applications multithread tout en masquant de nombreux problèmes complexes inhérents à la conception multithread. L’utilisation d’une classe qui prend en charge ce modèle peut vous permettre de :
Effectuez des tâches fastidieuses, telles que les téléchargements et les opérations de base de données, « en arrière-plan », sans interrompre votre application.
Exécutez plusieurs opérations simultanément, en recevant des notifications lorsque chaque opération est terminée.
Attendez que les ressources soient disponibles sans arrêter (« bloquant ») votre application.
Communiquez avec les opérations asynchrones en attente à l’aide du modèle d’événements et de délégués familiers. Pour plus d’informations sur l’utilisation de gestionnaires d’événements et de délégués, consultez Événements.
Une classe qui prend en charge le modèle asynchrone basé sur les événements aura une ou plusieurs méthodes nommées MethodNameAsync. Ces méthodes peuvent refléter des versions synchrones qui exécutent la même opération sur le thread actuel. La classe peut également avoir un événement MethodNameCompleted et elle peut avoir une méthode MethodNameAsyncCancel (ou simplement CancelAsync).
PictureBox est un composant classique qui prend en charge le modèle asynchrone basé sur les événements. Vous pouvez télécharger une image de façon synchrone en appelant sa Load méthode, mais si l’image est volumineuse ou si la connexion réseau est lente, votre application cesse de répondre jusqu’à ce que l’opération de téléchargement soit terminée et que l’appel à Load retourner.
Si vous souhaitez que votre application continue à s’exécuter pendant le chargement de l’image, vous pouvez appeler la LoadAsync méthode et gérer l’événement LoadCompleted , tout comme vous le feriez pour tout autre événement. Lorsque vous appelez la LoadAsync méthode, votre application continue à s’exécuter pendant que le téléchargement se poursuit sur un thread distinct (« en arrière-plan »). Votre gestionnaire d’événements est appelé lorsque l’opération de chargement d’images est terminée et votre gestionnaire d’événements peut examiner le AsyncCompletedEventArgs paramètre pour déterminer si le téléchargement s’est terminé avec succès.
Le modèle asynchrone basé sur les événements nécessite qu’une opération asynchrone puisse être annulée et que le PictureBox contrôle prend en charge cette exigence avec sa CancelAsync méthode. L’appel CancelAsync envoie une demande pour arrêter le téléchargement en attente et lorsque la tâche est annulée, l’événement LoadCompleted est déclenché.
Avertissement
Il est possible que le téléchargement se termine au fur et à mesure que la CancelAsync demande est effectuée. Il est donc Cancelled possible de ne pas refléter la demande d’annulation. Il s’agit d’une condition de concurrence et est un problème courant dans la programmation multithread. Pour plus d’informations sur les problèmes liés à la programmation multithread, consultez Les meilleures pratiques en matière de threads managés.
Caractéristiques du modèle asynchrone basé sur les événements
Le modèle asynchrone basé sur les événements peut prendre plusieurs formes, en fonction de la complexité des opérations prises en charge par une classe particulière. Les classes les plus simples peuvent avoir une méthode AsyncMethodName unique et un événement MethodNameCompleted correspondant. Des classes plus complexes peuvent avoir plusieurs méthodes AsyncMethodName, chacune avec un événement MethodNameCompleted correspondant, ainsi que des versions synchrones de ces méthodes. Les classes peuvent éventuellement prendre en charge l’annulation, les rapports de progression et les résultats incrémentiels pour chaque méthode asynchrone.
Une méthode asynchrone peut également prendre en charge plusieurs appels en attente (plusieurs appels simultanés), ce qui permet à votre code de l’appeler plusieurs fois avant d’effectuer d’autres opérations en attente. La gestion correcte de cette situation peut nécessiter que votre application effectue le suivi de l’achèvement de chaque opération.
Exemples de modèle asynchrone basé sur les événements
Les SoundPlayer composants et PictureBox les composants représentent des implémentations simples du modèle asynchrone basé sur les événements. Les composants et BackgroundWorker les WebClient composants représentent des implémentations plus complexes du modèle asynchrone basé sur les événements.
Voici un exemple de déclaration de classe conforme au modèle :
Public Class AsyncExample
' Synchronous methods.
Public Function Method1(ByVal param As String) As Integer
Public Sub Method2(ByVal param As Double)
' Asynchronous methods.
Overloads Public Sub Method1Async(ByVal param As String)
Overloads Public Sub Method1Async(ByVal param As String, ByVal userState As Object)
Public Event Method1Completed As Method1CompletedEventHandler
Overloads Public Sub Method2Async(ByVal param As Double)
Overloads Public Sub Method2Async(ByVal param As Double, ByVal userState As Object)
Public Event Method2Completed As Method2CompletedEventHandler
Public Sub CancelAsync(ByVal userState As Object)
Public ReadOnly Property IsBusy () As Boolean
' Class implementation not shown.
End Class
public class AsyncExample
{
// Synchronous methods.
public int Method1(string param);
public void Method2(double param);
// Asynchronous methods.
public void Method1Async(string param);
public void Method1Async(string param, object userState);
public event Method1CompletedEventHandler Method1Completed;
public void Method2Async(double param);
public void Method2Async(double param, object userState);
public event Method2CompletedEventHandler Method2Completed;
public void CancelAsync(object userState);
public bool IsBusy { get; }
// Class implementation not shown.
}
La classe fictive AsyncExample
a deux méthodes, qui prennent en charge les appels synchrones et asynchrones. Les surcharges synchrones se comportent comme n’importe quel appel de méthode et exécutent l’opération sur le thread appelant ; si l’opération prend du temps, il peut y avoir un délai notable avant le retour de l’appel. Les surcharges asynchrones démarrent l’opération sur un autre thread, puis retournent immédiatement, ce qui permet au thread appelant de continuer pendant l’exécution de l’opération « en arrière-plan ».
Surcharges de méthode asynchrone
Il existe potentiellement deux surcharges pour les opérations asynchrones : l’appel unique et l’appel multiple. Vous pouvez distinguer ces deux formulaires par leurs signatures de méthode : le formulaire d’appel multiple a un paramètre supplémentaire appelé userState
. Ce formulaire permet à votre code d’appeler Method1Async(string param, object userState)
plusieurs fois sans attendre la fin des opérations asynchrones en attente. Si, d’autre part, vous essayez d’appeler Method1Async(string param)
avant l’achèvement d’un appel précédent, la méthode déclenche un InvalidOperationException.
Le userState
paramètre des surcharges d’appel multiple vous permet de distinguer les opérations asynchrones. Vous fournissez une valeur unique (par exemple, un GUID ou un code de hachage) pour chaque appel et Method1Async(string param, object userState)
lorsque chaque opération est terminée, votre gestionnaire d’événements peut déterminer quelle instance de l’opération a déclenché l’événement d’achèvement.
Suivi des opérations en attente
Si vous utilisez les surcharges d’appel multiples, votre code doit suivre les userState
objets (ID de tâche) pour les tâches en attente. Pour chaque appel à Method1Async(string param, object userState)
, vous allez généralement générer un nouvel objet unique userState
et l’ajouter à une collection. Lorsque la tâche correspondant à cet userState
objet déclenche l’événement d’achèvement, votre implémentation de méthode d’achèvement examine AsyncCompletedEventArgs.UserState et supprime celle-ci de votre collection. Utilisé de cette façon, le userState
paramètre prend le rôle d’un ID de tâche.
Remarque
Vous devez être prudent pour fournir une valeur unique dans userState
vos appels à des surcharges d’appel multiples. Les ID de tâche non uniques entraînent la levée d’une ArgumentExceptionclasse asynchrone .
Annulation des opérations en attente
Il est important de pouvoir annuler des opérations asynchrones à tout moment avant leur achèvement. Les classes qui implémentent le modèle asynchrone basé sur les événements auront une méthode (s’il n’existe qu’une CancelAsync
seule méthode asynchrone) ou une méthode MethodNameAsyncCancel (s’il existe plusieurs méthodes asynchrones).
Les méthodes qui autorisent plusieurs appels prennent un userState
paramètre, qui peut être utilisé pour suivre la durée de vie de chaque tâche.
CancelAsync
prend un userState
paramètre, qui vous permet d’annuler des tâches en attente particulières.
Les méthodes qui ne prennent en charge qu’une seule opération en attente à la fois, comme Method1Async(string param)
, ne sont pas annulables.
Réception des mises à jour de progression et des résultats incrémentiels
Une classe qui respecte le modèle asynchrone basé sur les événements peut éventuellement fournir un événement pour le suivi de la progression et des résultats incrémentiels. Cela sera généralement nommé ProgressChanged
ou MethodNameProgressChanged, et son gestionnaire d’événements correspondant prendra un ProgressChangedEventArgs paramètre.
Le gestionnaire d’événements de l’événement ProgressChanged
peut examiner la ProgressChangedEventArgs.ProgressPercentage propriété pour déterminer le pourcentage d’une tâche asynchrone terminée. Cette propriété est comprise entre 0 et 100, et elle peut être utilisée pour mettre à jour la Value propriété d’un ProgressBar. Si plusieurs opérations asynchrones sont en attente, vous pouvez utiliser la ProgressChangedEventArgs.UserState propriété pour distinguer l’opération qui signale la progression.
Certaines classes peuvent signaler des résultats incrémentiels à mesure que les opérations asynchrones se poursuivent. Ces résultats sont stockés ProgressChangedEventArgs dans une classe qui dérive de et qui s’affiche en tant que propriétés dans la classe dérivée. Vous pouvez accéder à ces résultats dans le gestionnaire d’événements de l’événement ProgressChanged
, tout comme vous le feriez pour accéder à la ProgressPercentage propriété. Si plusieurs opérations asynchrones sont en attente, vous pouvez utiliser la UserState propriété pour distinguer l’opération qui signale les résultats incrémentiels.
Voir aussi
- ProgressChangedEventArgs
- BackgroundWorker
- AsyncCompletedEventArgs
- Guide pratique pour utiliser des composants qui prennent en charge le modèle asynchrone basé sur les événements
- Comment : exécuter une opération en arrière-plan
- Comment : implémenter un formulaire qui utilise une opération en arrière-plan
- Modèle asynchrone basé sur les événements (EAP)
- Meilleures pratiques pour l’implémentation du modèle asynchrone basé sur les événements
- Choix du moment où implémenter le modèle asynchrone basé sur les événements