36 votes

S'assurer que les choses fonctionnent sur le thread d'interface utilisateur dans WPF

Je suis en train de construire une application WPF. Je suis en train de faire quelques asynchrone de la communication avec le serveur, et j'utilise de l'agrégation d'événements avec Prisme sur le client. Ces deux choses en résulte de nouveaux fils est engendré, qui ne sont pas le thread d'INTERFACE utilisateur. Si je tente de faire "WPF opérations" sur ces de rappel et de gestionnaire d'événement de threads que le monde va s'écrouler, qu'elle a commencé à le faire.

D'abord, j'ai rencontré des problèmes en essayant de créer certains objets WPF dans le rappel de serveur. On m'a dit que le fil nécessaire pour exécuter dans le mode STA. Maintenant, je vais essayer de mettre à jour certaines données de l'INTERFACE dans un Prisme de gestionnaire d'événements, et je me suis dit que:

L'appelant ne peut pas accéder à ce fil, car un autre thread en est le propriétaire.

De la sorte; ce qui est la clé pour faire les choses dans WPF? J'ai lu sur le Répartiteur WPF dans ce MSDN post. Je commence à y arriver, mais je suis pas d'assistant.

  1. Est la clé de toujours utiliser un Répartiteur.Appeler quand j'ai besoin de faire quelque chose dont je ne suis pas sûr qu'elle sera appelée sur le thread d'INTERFACE utilisateur?
  2. Importe-t-il si elle a effectivement été appelé sur le thread de l'INTERFACE utilisateur, et je ne Répartiteur.Appeler de toute façon?
  3. Répartiteur.Appeler = de façon synchrone. Dispathcher.BeginInvoke = async?
  4. Va Dispatcher.Invoquer demande le thread de l'INTERFACE utilisateur, puis s'arrêter pour l'attendre? C'est une mauvaise pratique et un risque de moins de programmes sensibles?
  5. Comment puis-je obtenir le répartiteur de toute façon? Va Dispatcher.CurrentDispatcher me donnent toujours le répartiteur représentant le thread d'INTERFACE utilisateur?
  6. Sera-t-il exister plus d'un Répartiteur, ou est de "Dispatcher" essentiellement la même que le thread d'INTERFACE utilisateur pour l'application?
  7. Et quel est le problème avec le composant BackgroundWorker? Quand dois-je l'utiliser? Je suppose que c'est toujours asynchrone?
  8. Va sur tout ce qui fonctionne sur le thread d'INTERFACE utilisateur (par Invoquée) être exécuté en STA-appartement de mode? I. e. si j'ai quelque chose qui doit être exécuté dans le mode STA - va Dispatcher.Invoquer être suffisant?

Quelqu'un veux clearify choses pour moi? Toutes les recommandations, etc? Merci!

37voto

Charlie Points 9880

Passe sur chacune de vos questions, une par une:

  1. Pas tout à fait; vous devez seulement appeler sur le thread de l'INTERFACE utilisateur lorsque cela est nécessaire. Voir #2.
  2. Oui, c'est important. Vous ne devriez pas juste automatiquement Invoke tout. La clé est de ne invoquer sur le thread de l'INTERFACE utilisateur, si nécessaire. Pour ce faire, vous pouvez utiliser le Répartiteur.CheckAccess méthode.
  3. Qui est correct.
  4. Également correct, et oui, vous ne courez le risque de moins de programmes sensibles. La plupart du temps, vous n'allez pas être à la recherche à une sévère dégradation des performances (on parle de millisecondes pour un changement de contexte), mais vous ne devriez Invoke si nécessaire. Cela étant dit, à certains moments, il est inévitable, donc non, je ne dirais pas que c'est une mauvaise pratique à tous. C'est juste une solution à un problème que l'on rencontre chaque maintenant et puis.
  5. Dans tous les cas, je l'ai vu, je l'ai faite en raison des avec des Dispatcher.CurrentDispatcher. Pour des scénarios complexes, cela peut ne pas être suffisant, mais j'ai (personnellement) ne l'ont pas vu.
  6. Pas tout à fait correcte, mais cette ligne de pensée ne fera pas de mal. Permettez-moi de le dire de cette manière: l' Dispatcher peut être utilisé pour accéder à la thread de l'INTERFACE utilisateur de l'application. Mais il n'est pas, en soi, le thread d'INTERFACE utilisateur.
  7. BackgroundWorker est généralement utilisé lorsque vous avez un temps de fonctionnement et que vous souhaitez maintenir un réactif de l'INTERFACE utilisateur lors de l'exécution de cette opération en arrière-plan. Normalement, vous n'utilisez pas BackgroundWorker au lieu d'Invoquer, au contraire, vous utilisez BackgroundWorker en conjonction avec l' Invoquer. C'est, si vous avez besoin de mettre à jour des objets d'INTERFACE utilisateur dans votre BackgroundWorker, vous pouvez Appeler sur le thread de l'INTERFACE utilisateur, effectuer la mise à jour, puis revenir à l'opération d'origine.
  8. Oui. Le thread de l'INTERFACE utilisateur d'une application WPF, par définition, doit être en cours d'exécution dans un single-threaded apartment.

Il y a beaucoup à dire à propos de BackgroundWorker, je suis sûr que beaucoup de questions sont déjà consacrés à elle, donc je ne vais pas entrer dans trop de profondeur. Si vous êtes curieux, découvrez la page MSDN pour la classe BackgroundWorker.

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