8
votes

Application WPF multi-threadé: Dispatcher invoquez. Une manière plus efficace?

J'utilise .NET 3.5.

Je fais une application WPF pour un projet et que je visitant un peu de perspicacité concernant le répartiteur et la multithreading. Un exemple de mon programme: xxx

Je comprends que WPF n'aime pas quand un autre fil accédant à un objet autre que celui qui l'a créée. Cependant, je pensais qu'il y avait sûrement une meilleure façon que de faire appel autant d'invoques, pourrait-on me pousser à me pousser dans la bonne direction au moins (s'il y a une meilleure solution).


0 commentaires

4 Réponses :


13
votes

Le moyen le plus simple serait de combiner les trois appels en un: xxx


3 commentaires

Je ne savais pas que c'était possible, apprenez quelque chose de nouveau tous les jours! À votre santé.


@Sparky: Tout ce que vous faites avec le => crée une expression Lambda, qui est un type de délégué anonyme. Ce sont tous des sucres syntaxiques que le compilateur finit par se transformer en méthodes ordinaires (ou parfois statiques). Vous pouvez faire n'importe quoi dans une expression de Lambda (quand il est utilisé comme délégué anonyme, comme il est ici) que vous pouvez faire dans une fonction ordinaire, à l'exception de (éventuellement; je n'ai pas vérifié) ref et out paramètres.


Cela a fonctionné pour moi, s'est débarrassé de l'exception d'impression: le fil d'appel ne peut pas accéder à cet objet car un thread différent est propriétaire., StackTrace: à System.Windows.threading.Dispatcher.VendyAccess ()



6
votes

Si vous utilisez .NET 4.0, je m'empêcherais d'utiliser System.Threading.Tasks . Cela ressemble à un excellent exemple pour Continuations .


5 commentaires

Les tâches ne vous aideront pas s'il est déjà en dehors du filetage de la pompe à message (où la synchronisation automatique serait utile)


Bien sûr, car vous pouvez planifier vos tâches "arrière-plan" sur un fil d'arrière-plan, puis "finir" avec une suite sur le thread de l'interface utilisateur comme: Tâche.Continuewith (Finmermystuff, Taskscheduler.fromcurrentSynchronizationContext)


Bien sûr, si l'OP est en mesure de déplacer tout le code actuel en tâches et de placer tout sur la fenêtre / le contrôle. Cependant, s'il n'est pas en mesure de retravailler tout le modèle de threading, les tâches ne vous aideront pas.


@Adamrobinson bien il demandait "Insight" et il n'offrait aucune restriction, alors j'ai offert ce que je pensais être la meilleure "idée" que j'avais. Il est libre de l'ignorer s'il choisit.


Salut les gars, merci beaucoup pour les réponses, malheureusement, je ne peux pas les implémenter comme j'utilise .NET 3.5 :) Néanmoins, je vais rechercher la mention ci-dessus pour la référence future! À votre santé



16
votes

Vous pouvez commencer par être moins verbose dans vos appels, c'est-à-dire

UiInvoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));


4 commentaires

J'aime cette idée! Merci. J'ai 2 threads exécutés dans la classe d'une classe: 1 pour obtenir des données pour la base de données, l'autre pour la délivrance d'une émergence d'une économie de vitesse pour mettre à jour l'interface utilisateur. Je comprends que ce n'est probablement pas la meilleure façon de faire les choses, d'être honnête, je ne suis pas un expert en WPF, donc l'idée d'un fil d'interface utilisateur et des travailleurs de fond est un peu étranger à moi à la minute


Non, c'est à peu près la façon dont les choses sont faites dans WPF, alors je woukd dire que votre approche est tout à fait bien. Je conviendrai que cela peut être une douleur pour faire les affaires de l'interface utilisateur, mais un mal nécessaire, je suppose. Le codage Gorilla fait également un bon point ci-dessus sur les continuations, mais ceux-ci peuvent être informés dans le territoire super-slop. Bonne chance!


Je ne pense pas que cela soit "à peu près comment les choses sont faites dans WPF". La liaison des données doit être expédiée automatiquement. Surtout s'il utilise mvvm. Voir ma réponse mise à jour.


@EUPHORIC: C'est tout bien et bien pour les liaisons, mais ce n'est clairement pas le cas ici. De plus, vous ne pouvez pas faire des hypothèses sur les interactions les plus complexes de son code. Donc, vous êtes à peu près laissé pour faire l'envoi de vous-même.



3
votes

Votre problème provient du fait que Observablecollection ne modifie pas l'automatisme des modifications apportées au fil de l'interface utilisateur. Ceci est une forme différente de l'inotifypropertychangned, qui l'a fait automatiser. Je recommanderais de créer votre propre observa d'observateur spécifique, qui implémente InotifyCollectionChangiesD, que l'automatisée dépêche des modifications apportées au fil de l'UI.

Vous pouvez voir l'exemple ici: synchronizedobservablecollection et BindableCollection

Ancienne réponse / question: Utilisez-vous DépendencyObject et dépendanceProperty Pour votre reliure? Si oui, puis tombez-le. Il a été discuté à plusieurs reprises et c'est l'une des plus grandes raisons pour lesquelles utiliser inotifypropertychangned à la place. Il suffit d'utiliser le répartiteur consiste à modifier les propriétés des objets d'interface graphique elles-mêmes et son évident de votre exemple, ce n'est pas ce que tu fais. Et se lier elle-même est exécutée à travers le répartiteur automatisé.

Voir aussi Voir les modèles: Pocos contre dépendanceObjects


3 commentaires

Salut euphorique, acclamations, mais non, je n'utilise pas les propriétés de la dépendance. En outre, j'utilise MVVM Light, donc j'utilise actuellement "SUPPROPERTYCHANGED" sur "INOTICYPROPERTYCHANGED". Merci


C'est bizarre. Alors, quels sont _acollection, _data et _historical dans votre exemple? S'ils ne font pas partie de l'interface graphique, il n'est pas nécessaire de les modifier via le répartiteur. Et je ne vois pas besoin d'utiliser le répartiteur lors de l'utilisation de MVVM.


Hmmm ... bien dans ce cas, comment allez-vous contourner le problème où les threads non nommés accèdent à une collection observable? _Data sont des points de graphique pour Visiblox et _Acollection est une collection survetable liée à la liste