Question

Je suis vraiment embarrassé de poser une question aussi triviale, mais le débogage de certains logiciels m'a maintenant convaincu que je ne comprenais pas vraiment ce problème:

Comment fonctionnent les événements .NET vus à une altitude de 20 000 pieds? Je ne parle pas du modèle de délégué / gestionnaire d'événements et de tout cela. Ce que je veux dire, c'est: quelle est la GRANDE image:

  1. Le code A fait quelque chose.
  2. Certains déclencheurs externes se produisent. Supposons, par exemple, que l'utilisateur ait cliqué sur un contrôle.
  3. Une magie se produit et le gestionnaire d'événements de l'événement est appelé.
  4. une autre magie se produit après le retour du gestionnaire d'événements.

Maintenant, quelle est la magie? Comment cela se rapporte-t-il aux discussions? Le thread qui exécute mon code est-il interrompu lorsque l'événement se produit, puis reprend après le retour du gestionnaire d'événements? Mais j’ai cherché sur Google et découvert que les gestionnaires .NET sont appelés de manière synchrone le fil d'origine. Alors, qui s'occupe d'arrêter et de reprendre le code A? Que se passe-t-il si des événements sont imbriqués (c.-à-d. Que l'événement 2 se produit lorsque le gestionnaire d'événements pour l'événement 1 est en cours d'exécution)?

Modifier : Autant que je sache, les réponses indiquent que le gestionnaire d'événements de l'événement suivant ne sera exécuté qu'une fois le gestionnaire d'événements en cours d'exécution terminé. Cela signifie que votre code n'est pas interrompu: la ligne n sera toujours exécutée immédiatement après la ligne n-1 et juste avant la ligne n + 1. Cependant, juste avant d'avoir posté la question, je déboguais un programme en contrôlant, via l'automatisation, Internet Explorer (à l'aide de SWExplorerAutomation de Webius). Je suis tout à fait sûr que pendant que je parcourais le code, j'étais "kidnappé". :-) à un gestionnaire d’événements et est retourné à la position interrompue dans le code une fois que ce gestionnaire d’événements a terminé ses activités. Cela signifie soit que vous ne comprenez pas les réponses, soit que le programme se comporte différemment tout en passant par le débogueur!

Était-ce utile?

La solution

Laissez-moi vous éclairer sur votre problème. La magie est la boucle de messages Windows. Vous voyez dans votre exemple, en fait, rien ne fait arrêter Code A lorsqu'un événement se produit. C’est plutôt la séquence.

Lorsque le code A est en cours d’exécution, l’utilisateur clique sur un bouton. Le message de la fenêtre du bouton est mis en file d'attente, mais rien ne se passe. Lorsque le code A quitte sa fonction ou abandonne le contrôle à la boucle de messages, l'événement Click est traité et le gestionnaire d'événements est exécuté.

Essayez cette expérience. Placez une boucle infinie dans votre programme sur le fil principal, puis cliquez sur l'interface utilisateur. Vous remarquerez que l'interface utilisateur ne répondra plus et qu'aucun gestionnaire d'événement ne sera en cours d'exécution.

Autres conseils

Ce que vous verrez à partir de 20 000 pieds est le MessageLoop . C'est à l'intérieur de Application.Run () .

En termes simples, il s’agit d’une boucle while qui exécute la totalité de la durée de vie de votre application et

  // pseudo code, I did not reflector Application.Run
  while (GetMessage(ref msg)
  {
     DispatchMessage(ref msg);
  }

Vous remarquerez que le fil-simgle est trop long lorsque vous gérez un événement, votre application sera étiquetée "ne répond pas" dans le Gestionnaire des tâches.

Une méthode connexe est Application.DoEvents () , mais évitez cela.

Les événements sont des pointeurs vers des fonctions (comme nous le faisions auparavant en C ++). Lorsque vous utilisez un événement .NET plain vanilla, vous appelez en fait les fonctions connectées à l'aide de + = à cet événement. Ainsi, à partir de 20 000 pieds, votre code appelle un autre code, tout comme une autre fonction. C'est pourquoi il est appelé de manière synchrone et dans le même fil.

Lorsque vous vous trouvez dans le contrôle WinForms / WPF, vous devez également prendre en compte une boucle de message: Tous les événements qui se produisent dans le contexte du formulaire ajoute un message à la boucle de message au lieu d'appeler directement une méthode.

Le thread principal du contrôle interroge cette boucle pour les nouveaux messages. Lorsqu'un nouveau message apparaît, il l'exécute (encore une fois dans le thread principal), mais ce n'est pas tout à fait synchrone.

C'est la raison pour laquelle si un formulaire est occupé à faire quelque chose et que vous appuyez sur un bouton, cela prend un certain temps avant que vous n'appuyiez sur ce bouton. c’est aussi la raison pour laquelle si vous invalidez un contrôle, son apparence n’est modifiée que lorsque vous quittez la méthode en cours d’exécution (et le message suivant est traité).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top