Quelles solutions ai-je si je souhaite empêcher l'interface utilisateur de geler pendant que je désexiste un grand nombre d'éléments d'interface utilisateur dans WPF? Je reçois des erreurs que les objets appartiennent au fil de l'interface utilisateur lorsque j'essaie de les charger dans un autre fil. Ainsi, quelles options dois-je empêcher l'erreur "Programme de non-réponse" de Vista pendant que je charge mes données d'interface utilisateur? Puis-je compter sur une solution à une seule fois filetée, ou je manque quelque chose à propos de plusieurs threads d'interface utilisateur? P>
7 Réponses :
Si vous n'utilisez qu'un seul thread, l'interface utilisateur gèlera pendant que vous effectuez une quantité de traitement.
Si vous utilisez un fil d'antécédents, vous aurez plus de contrôle sur ce qui se passe et quand. P>
Pour mettre à jour l'interface utilisateur, vous devez utiliser Dispatcher.invoke Code>
à partir de votre fil d'arrière-plan pour remercier l'appel sur la limite de fil. P>
Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => this.TextBlock.Text = "Processing");
Vous pouvez toujours effectuer votre long traitement dans un thread séparé, mais lorsque vous avez terminé, vous devez synchroniser avec le fil de l'interface utilisateur en appelant Dispatcher.begininvoke (your_ui_action_here) code> p> p> P>
Recommandations de l'ancien blog. P>
Il est préférable que vous puissiez aller à la route filetée, pour avoir un fil d'interface graphique et reproduire votre charge de travail sur un autre fil qui se termine lorsque vous finissez dans le fil de l'interface graphique principale que celui-ci fait. La raison en est que vous n'obtiendrez pas dans des problèmes de fil avec votre interface GUI. P>
SO One Thread Gui Beaucoup de threads travailleurs qui font le travail. P>
Si l'un de vos threads accrochent, l'utilisateur est sous contrôle direct sur votre application, vous pouvez fermer le fil sans effectuer son expérience avec l'interface d'application. Cela le rendra heureux parce que votre utilisateur se sentira en contrôle autre que lui, cliquez constamment sur ce bouton d'arrêt et il n'arrête pas d'arrêter la recherche. P>
Essayez congeler vos uelements. Les objets congelés peuvent être passés entre les filets sans rencontrer une intimidation invalidorationException, de sorte que vous les désérialisez et les gèlent sur un fil d'arrière-plan avant de les utiliser sur votre fil d'interface utilisateur. P>
Alternativement, envisagez de renvoyer les désérialisations individuelles à la filetage de l'interface utilisateur à la priorité de base. Ce n'est pas optimal, car le fil d'interface utilisateur doit toujours faire tout le travail pour désérialiser ces objets et il y a des frais généraux ajoutés en les envoyant en tant que tâches individuelles, mais au moins vous ne bloquerez pas les événements prioritaires de l'interface utilisateur. sera capable d'être entrecoupé avec votre travail de désérialisation prioritaire inférieur. P>
Cela ne fonctionne que pour les congélables et les éléments d'UI ne sont pas conçus. Donc, si vous parlez de créer une géométrie, des brosses, etc. Cela fonctionne, mais si vous parlez de construire des éléments d'interface utilisateur (c'est-à-dire une classe visuelle et de la chaîne d'héritage).
Voici un merveilleux blog en affichage de Dwnane Besoin qui discute de toutes les options disponibles pour travailler avec des éléments UI parmi plusieurs threads. P>
Vous n'avez vraiment pas donné suffisamment de détails pour donner une bonne ordonnance. Par exemple, pourquoi créez-vous des éléments d'interface utilisateur vous-même au lieu d'utiliser la base de données? Vous pourriez avoir une bonne raison, mais sans plus de détails, il est difficile de donner de bons conseils. Comme un autre exemple de détail qui serait utile, cherchez-vous à construire des hiérarchies de contrôle complexes profondément imbriquées pour chaque morceau de données ou avez-vous juste besoin de dessiner une forme simple? P>
Vous pouvez transformer le flux de contrôle sur sa tête en utilisant des caractères répartis, permettant à une désérialisation de procéder sur le fil de l'interface utilisateur en arrière-plan.
Vous avez d'abord besoin d'un moyen de contrôler périodiquement lors de la désérialisation. Quel que soit le désérialiseur que vous utilisez, il devra appeler des ensembles de propriétés sur vos objets. Vous pouvez donc généralement ajouter du code aux configurateurs de propriétés. Sinon, vous pouvez modifier le désérialiseur. Dans tous les cas, assurez-vous que votre code est appelé assez souvent p>
chaque fois que vous recevez le contrôle, tout ce que vous avez à faire est: p>
En outre, lorsque vous appelez le désérialiseur lui-même, assurez-vous de le faire de Dispatcher.begininvoke, ou que votre code d'appel ne conserve aucune serrure, etc. P>
Voici comment ça se passe : p> vérifiant la datetime.now in Dreevents () n'est pas nécessaire pour que cette technique fonctionne, mais améliorera les performances si une certaine exportation est définie très fréquemment pendant la désérialisation. P> EDIT: strong> Juste après avoir écrit cela, j'ai réalisé qu'il existe un moyen plus facile de mettre en œuvre la méthode des départs. Au lieu d'utiliser DispatcherFrame, utilisez simplement Dispatcher.Invoke avec une action vide: p>
J'ai eu un problème similaire avec mon panneau qui déplaçait ses articles. L'interface utilisateur était gelée parce que j'utilisais un dispattertimer à la priorité chargée. Le problème est allé dès que je l'ai changé vers DispatcherPriority.input. P>
Dans Windows Formulaires, vous pouvez utiliser Application.Deevents (). Je ne sais pas si cela fonctionne dans WPF.