2010-05-05 10 views
1

J'ai un comportement étrange dans mon code GUI. Si l'utilisateur produit beaucoup d'événements dans un court laps de temps, il arrive qu'une méthode de gestion d'événement en cours soit interrompue par une autre méthode de gestionnaire d'événement. Puisque tout tourne dans le même thread (thread graphique), tout devrait fonctionner séquentiellement et une interruption ne devrait pas être possible, ou est-ce que je ne comprends pas quelque chose?Est-il possible qu'un événement d'interface graphique interrompe le code en cours d'exécution à partir du thread d'interface graphique pour exécuter sa propre méthode de gestionnaire d'événements?

Merci pour votre conseiller, Eny

+0

Des échantillons pour ces événements? Vous ne parlez pas d'un événement Timer, par exemple? –

+1

Vous avez raison, le thread graphique devrait exécuter les choses de manière séquentielle. Comment savez-vous que ces interruptions se produisent? – Paolo

+0

@Benjamin Non, pas de minuteur est impliqué, je l'ai déjà vérifié, il est vraiment dans le même fil. Les événements sont par exemple Nœud de mise au point modifié à l'intérieur d'un contrôle de liste d'arbres. @Paolo J'enregistre ce qui se passe, incl. informations sur les threads etc. Et j'obtiens des états d'application erronés qui ne peuvent pas se produire s'ils sont séquentiels. – Enyra

Répondre

4

Non, cela ne se produit pas. Vous avez raison de comprendre que le thread s'exécute de manière séquentielle.

Le thread graphique peut être interrompu, mais uniquement pour exécuter un thread différent, il ne rentrera pas dans le thread graphique pour gérer un autre événement. Un thread n'a qu'un seul pointeur d'instruction et ne peut donc être que dans un seul endroit du code, il ne peut pas être interrompu par lui-même.

Si vous rencontrez quelque chose qui ressemble à la thread graphique est ré-entré, la raison en est autre chose.

Le sujet graphique peut toutefois "s'interrompre" en appelant la méthode Application.DoEvents.

+0

Le Application.DoEvents est un bon indice, je dois rechercher le code si cela est utilisé quelque part. – Enyra

+0

Oui c'était ça, merci. – Enyra

3

Vous avez raison, dans une application à un seul thread, l'événement doit être exécuté de manière séquentielle. Il existe quelques exceptions:

  1. Un événement est déclenché et appelle le premier gestionnaire d'événements dans sa liste d'abonnés. Le gestionnaire d'événements déclenche un événement propre, qui appelle d'autres gestionnaires d'événements. Dans ce cas, il semblerait que l'événement a été interrompu, mais ce n'était pas le cas. Lorsque le gestionnaire d'événements d'origine est terminé, le gestionnaire d'événements suivant de la liste est appelé. Un gestionnaire d'événements appelle la méthode Application.DoEvents(). Cela va suspendre l'événement en cours et traiter tous les messages en attente dans la file d'attente des messages (qui génèrera généralement ses propres événements), et lorsqu'il aura fini de traiter tous les messages, il retournera à l'événement. Un problème peut survenir lorsque Application.DoEvents() provoque un appel récursif à l'événement qui l'a appelé, à la suite du déclenchement d'un événement à partir de l'un des messages qu'il a traités.

  2. Les gestionnaires d'événements peuvent être exécutés sur différents threads. Certains événements ne sont pas déclenchés sur le thread d'interface utilisateur et peuvent se déclencher sur leur propre thread. Cela peut provoquer le déclenchement d'événements dans le désordre et s'interrompre sur un commutateur de contextes de threads. Assurez-vous que les événements que vous consommez sont déclenchés sur le thread de l'interface utilisateur et, dans le cas contraire, Control.Invoke() sur le thread de l'interface utilisateur. Un exemple d'événement déclenché sur un thread séparé, sans que vous en soyez conscient, est l'événement System.Threading.Timer.Elapsed.

+0

Il n'y a pas de temps ou quoi que ce soit d'autre, ce qui pourrait produire un autre thread et je vérifie déjà qu'il se passe réellement dans le même thread qu'un gestionnaire d'événement no est appelé manuellement. Mais Application.DoEvents pourrait être possible, je vais le vérifier maintenant. – Enyra