283 votes

Utilisation de Application.DoEvents ()

Est-ce que Application.DoEvents() peut être utilisé en C #?

Cette fonction permet-elle à l'interface graphique de rattraper le reste de l'application, à peu près de la même manière que DoEvents VB6?

488voto

Hans Passant Points 475940

Hmya, la pérennité de la mystique de la fonction DoEvents(). Il y a eu une énorme quantité de réaction contre elle, mais personne ne l'a jamais vraiment explique pourquoi il est "mauvais". Le même genre de sagesse "ne pas muter un struct". Euh, pourquoi le moteur d'exécution et la langue prend en charge la mutation d'un struct si c'est si mauvais? Même raison: vous vous tirez dans le pied, si vous ne le faites pas droit. Facilement. Et pour ce faire, il nécessite de connaître exactement ce qu'il fait, qui, dans le cas de la fonction DoEvents() n'est certainement pas facile à analyser.

Le droit au large de la chauve-souris: presque tous les Winforms programme contient en fait un appel à la fonction DoEvents(). Il est habilement déguisé mais avec un nom différent: ShowDialog(). C'est la fonction DoEvents() qui permet une boîte de dialogue modale sans elle gel le reste de la windows dans l'application.

La plupart des programmeurs souhaitez utiliser la fonction DoEvents pour arrêter leur interface utilisateur de gel quand ils écrivent leur propre modal de la boucle. C'est certain que, il envoie des messages de Windows et obtient la peinture des demandes livrées. Le problème, toutefois, est qu'il n'est pas sélective. Il ne distribue uniquement des messages de peinture, il offre tout le reste aussi.

Et il y a un ensemble de notifications qui causent des problèmes. Ils viennent d'environ 3 pieds en face de l'écran. L'utilisateur pourrait, par exemple, fermez la fenêtre principale, tandis que la boucle qui appelle la fonction DoEvents() est en cours d'exécution. Qui fonctionne, l'interface utilisateur est allé. Mais votre code n'a pas arrêter, elle est toujours en cours d'exécution de la boucle. C'est un mauvais. Très, très mauvais.

Il y a plus: l'utilisateur peut cliquer sur le même élément de menu ou un bouton qui provoque la même boucle pour commencer. Maintenant, vous avez deux boucles imbriquées l'exécution de la fonction DoEvents(), la précédente boucle est interrompue et la nouvelle boucle est de commencer à partir de zéro. Cela pourrait fonctionner, mais le garçon les chances sont minces. Surtout quand la boucle imbriquée se termine et que la suspension d'un curriculum vitae, en essayant de terminer un travail qui a déjà été complétée. Si ce n'est pas de la bombe avec une exception alors sûrement que les données sont brouillés tous en enfer.

Retour à ShowDialog(). Il exécute la fonction DoEvents (), mais ne remarque qu'il fait quelque chose d'autre. Il désactive toutes les fenêtres de l'application, autre que la boîte de dialogue. Maintenant que 3 pieds problème est résolu, l'utilisateur ne peut pas ne rien gâcher la logique. Les deux près de la fenêtre et démarrez-le-travail-nouveau modes de défaillance sont résolus. Ou pour le dire d'une autre façon, il n'y a aucun moyen pour l'utilisateur de faire votre programme d'exécuter du code dans un ordre différent. Il exécutera de manière prévisible, tout comme il l'a fait quand vous avez testé votre code. Il rend les dialogues extrêmement ennuyeux, qui n'a pas la haine d'avoir un dialogue actif et ne pas être en mesure de copier et coller quelque chose à partir une autre fenêtre? Mais c'est le prix.

Qui est ce qu'il faut pour utiliser la fonction DoEvents en toute sécurité dans votre code. Le réglage de la propriété Enabled de tous vos formulaires pour le faux est un moyen rapide et efficace pour éviter les problèmes. Bien sûr, aucun programmeur ne jamais en fait il aime le faire. Et qui ne fonctionne pas. C'est pourquoi vous ne devriez pas utiliser la fonction DoEvents(). Vous devez utiliser les threads. Même si ils vous remettre un arsenal complet de moyens de tirer votre pied dans les couleurs et les voies impénétrables. Mais avec l'avantage que vous ne tirez vos propres pieds, il ne va pas (généralement) permettent à l'utilisateur de tirer la sienne.

Les prochaines versions de C# et VB.NET fournira une arme différente avec la nouvelle attendent et asynchrone des mots-clés. Inspiré en partie par les problèmes causés par la fonction DoEvents et les threads, mais en grande partie par l'api WinRT conception qui exige de vous pour garder votre INTERFACE utilisateur mis à jour lorsqu'une opération asynchrone. Comme la lecture à partir d'un fichier.

30voto

RQDQ Points 8896

Peut être, mais c'est un hack.

http://www.codinghorror.com/blog/2004/12/is-doevents-evil.html

EDIT: Directement à partir de la page MSDN qui thedev référencé:

L'appel de cette méthode provoque le courant thread suspendu pendant que tous les en attente de la fenêtre de messages sont traités. Si un message causes d'un événement déclenché, puis d'autres zones de votre le code de l'application peut s'exécuter. Cela peut la cause de votre demande d'admission comportements inattendus qui sont difficile à déboguer. Si vous effectuez des opérations ou des calculs qui prennent un depuis longtemps, il est souvent préférable d' effectuer ces opérations sur un nouveau fil de discussion. Pour plus d'informations sur la programmation asynchrone, voir La Programmation Asynchrone Vue D'Ensemble.

Donc MS met en garde contre son utilisation.

Aussi, je considère que c'est un hack parce que son comportement est imprévisible et effet de bord ventral (cela vient de l'expérience d'essayer d'utiliser la fonction DoEvents au lieu de tourner un nouveau fil ou à l'aide d'arrière-plan pour les travailleurs).

Il n'y a pas de machisme ici - si elle a fonctionné comme une solution robuste, je serais sur elle. Cependant, essayez d'utiliser la fonction DoEvents .NET m'a fait rien que de la douleur.

24voto

Bill W Points 484

Application.DoEvents() est utilisée pour pomper des messages dans le thread de l'INTERFACE utilisateur lors de l'exécution d'un travail de longue haleine dans le thread de l'INTERFACE utilisateur. C'est presque toujours pas la meilleure façon de faire les choses. Il est beaucoup mieux de faire des tâches complexes dans un autre thread. Regardez ici pour plus de détails.

Ici est la bonne façon de faire les choses.

12voto

Craig Johnston Points 1350

De mon expérience, je conseillerais une grande prudence avec l'utilisation de DoEvents dans .NET. J'ai rencontré des résultats très étranges lors de l'utilisation de DoEvents dans un TabControl contenant DataGridViews. D'un autre côté, si tout ce que vous avez à faire est un petit formulaire avec une barre de progression, cela pourrait être OK.

La ligne de fond est: si vous allez utiliser DoEvents, alors vous devez le tester à fond avant de déployer votre application.

11voto

Frederik Gheysels Points 36354

Oui.

Cependant, si vous avez besoin d'utiliser Application.DoEvents , c'est surtout une indication d'une mauvaise conception d'application. Peut-être que vous aimeriez faire du travail dans un fil séparé à la place?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X