2009-07-16 7 views
3

J'ai trouvé que certains de mes contrôles d'application winform, tels que DataGridView et ToolStrips, sont référencés par UserPreferenceChangedEventHandlers. Je n'ai aucune idée du paramétrage des contrôles qui va générer de telles références et pourquoi de telles références gardent mon contrôle vivant en mémoire. Comment puis-je supprimer de telles références de cet événement? Merci.Qu'est-ce que UserPreferenceChangedEventHandler dans les applications winform C#?

Répondre

7

Il s'agit du type de délégué pour l'événement SystemEvents.UserPreferenceChanged. Cet événement se déclenche lorsque Windows diffuse le message WM_SETTINGCHANGE. Ce qui se produit généralement lorsque l'utilisateur utilise une applet du panneau de configuration et modifie un paramètre système.

Plusieurs contrôles enregistrent un gestionnaire d'événements pour cet événement, DataGridView, DateTimePicker, MonthCalendar, ProgressBar, PropertyGrid, RichTextBox, ToolStrip, NumericUpDown. Ils sont généralement intéressés par les changements de police ou de cue et tout ce qui pourrait affecter la mise en page.

SystemEvents.UserPreferenceChanged est un événement statique. L'enregistrement d'un gestionnaire et l'oubli de l'annulation entraînent une fuite de mémoire, ce qui empêche le contrôle d'être récupéré. Les contrôles répertoriés assurent que cela ne se produit pas, ils désenregistrent le gestionnaire d'événements dans la méthode OnHandleDestroyed() ou Dispose().

Vous rencontrerez des problèmes si aucune de ces deux méthodes ne fonctionne. Cela se produira lorsque vous supprimerez le contrôle de la collection Controls du conteneur et que vous oublierez de le supprimer. Bien qu'oublier d'appeler Dispose() ne pose normalement pas de problème, c'est une exigence pour les contrôles. Il est facile d'oublier aussi, les contrôles sont normalement automatiquement éliminés par le formulaire. Mais cela ne se produit que pour les contrôles de la collection Controls.

Veillez également à appeler Dispose() sur les formulaires que vous affichez avec la méthode ShowDialog() après avoir obtenu les résultats de la boîte de dialogue. L'instruction using est la meilleure façon de gérer cela.


Un détail atroce est important de l'événement UserPreferenceChanged, il est souvent celui qui DEADLOCKS votre application lorsque vous créez des contrôles sur un thread de travail. Généralement lorsque le poste de travail est verrouillé (appuyez sur Win + L). La classe SystemEvents essaye de déclencher l'événement sur le thread de l'interface utilisateur mais ne peut bien sûr pas le faire correctement lorsque plus d'un thread les a créés.

De même, le type de bogue qui peut avoir un effet durable, un écran de démarrage peut, par exemple, amener la classe SystemEvents à deviner quel thread est votre thread d'interface utilisateur. Après quoi, il soulève alors définitivement l'événement sur le mauvais fil. Très moche to diagnose, l'impasse est bien caché.

+0

Nous vous remercions de votre suggestion. J'ai vérifié le code et il semble que le contrôle problématique a été ajouté à la liste de contrôle d'un panneau et le panneau a été ajouté à la liste de contrôle d'un autre panneau et enfin le panneau racine a été ajouté à la liste de contrôle du formulaire. À partir du profileur de mémoire, je peux également voir que la méthode disposer du contrôle a été appelée mais que UserPreferenceChangedEventHandler se bloque toujours. C'est la partie que je ne comprends pas. Y a-t-il d'autres choses que j'ai ratées? – Steve

+0

Mais merci pour la réponse. Je vais le prendre. – Steve

+0

Bonne réponse MAIS comme le mentionne Steve, parfois même si vous disposez du contrôle, vous avez toujours ce problème. Il existe plusieurs entrées Connect à propos de ce problème, telles que: http://connect.microsoft.com/VisualStudio/feedback/details/469277/toolstrip-statusstrip-toolstriptextbox-visibility-and-userpreferencechangedeventhandler. –

Questions connexes