ProgrammationDéveloppeur de bureau (WinForms, VB.NET)

Comment la gestion des files d'attente d'événements (event queue) et des appels asynchrones est-elle réalisée en Visual Basic et quelles sont les différences entre les différentes méthodes (DoEvents, BackgroundWorker, Async/Await) ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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.
  • Les mots clés 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.

Question piège.

Quel est le danger d'utiliser DoEvents dans 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

Dans la pratique, il y a eu un cas : lors de la migration d'une application VB6 vers VB.NET, 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

Dans un projet de logiciel financier, un des employés a tenté de mettre à jour un graphique sur le formulaire avec 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.