En Visual Basic, les appels asynchrones et la gestion des événements sont souvent réalisés de différentes manières, en fonction de la version du langage et du type d'application. Dans les applications WinForms classiques VB.NET, la gestion de la file d'attente des événements (event queue) suppose généralement l'appel de Application.DoEvents(). Cette méthode permet au gestionnaire d'événements de "libérer le contrôle" afin que d'autres messages puissent être traités sans bloquer le thread principal:
While loading Application.DoEvents() 'Permet à l'interface utilisateur de réagir aux actions de l'utilisateur End While
Pour l'exécution asynchrone de tâches dans .NET avec VB.NET, on utilise:
BackgroundWorker — un composant WinForms pour déplacer les opérations longues dans un thread séparé tout en interagissant en toute sécurité avec le thread UI.Async/Await — un système moderne pratique d'asynchronie, apparu dans .NET 4.5, qui permet d'écrire du code asynchrone "comme synchrone":Public Async Function LoadDataAsync() As Task Dim result As String = Await GetWebDataAsync() TextBox1.Text = result End Function
Différences:
DoEvents traite simplement la file d'attente des messages de l'UI et ne crée pas de nouveaux threads.BackgroundWorker déplace le travail dans un thread séparé, avec un événement pour un retour sécurisé dans le thread UI.Async/Await implémente l'asynchronie tout en encapsulant le retour du contrôle au thread UI.Quel est le danger d'utiliser
DoEventsdans une boucle, si nous devons charger un fichier depuis un disque et mettre à jour ProgressBar ?
Réponse:
DoEvents transfère temporairement le contrôle à d'autres événements Windows, mais ne libère pas le thread. Si on l'utilise dans des boucles lourdes (comme la lecture d'un gros fichier tout en mettant à jour l'interface), des bugs inattendus peuvent survenir: les événements de l'utilisateur et les événements souris seront traités, ce qui peut entraîner le redémarrage du traitement ou même le "gel" de l'application. Si une charge lourde est prévue, il convient d'utiliser BackgroundWorker ou Task.
Exemple d'approche incorrecte:
For i = 1 To 1000000 ProgressBar1.Value = i / 10000 Application.DoEvents() 'Ne libère pas le thread principal! Next
Histoire
DoEvents a été utilisé à l'intérieur d'une boucle de lecture de fichier pour mettre à jour l'indicateur de progression. En conséquence, l'interface "gelait": si l'utilisateur cliquait à nouveau sur le bouton "Ouvrir", un second processus de lecture de fichier commençait, en mélangeant avec le premier, provoquant une distorsion des données et un crash de l'application.Histoire
DoEvents dans une boucle, car il ne connaissait pas BackgroundWorker. Lors de la mise à jour d'un ensemble de points énorme, l'application a commencé à se bloquer et a fini par "planter" à cause d'un débordement de la file d'attente des messages Windows.Histoire
Un appel asynchrone a été utilisé via Async/Await, sans comprendre que des travaux longs ne pouvaient pas être lancés dans le thread UI "chaud" sans Await Task.Run(...). Résultat : l'interface ne réagissait pas aux clics, et la barre de progression ne s'actualisait pas, car la méthode longue s'exécutait toujours sur le thread principal.