Où puis-je obtenir un thread-safe CollectionView?
Lors de la mise à jour d'une collection de business objects sur un thread d'arrière-plan, j'obtiens ce message d'erreur:
Ce type de CollectionView ne prend pas en charge les modifications de son SourceCollection à partir d'un thread différent de l'expéditeur au fil.
Ok, qui fait sens. Mais cela pose également la question, quelle est la version de CollectionView prend en charge plusieurs threads et comment puis-je faire mes objets à utiliser?
- Essayez le lien suivant qui fournit un thread-safe solution qui fonctionne à partir de n'importe quel thread, et peut être lié à l'aide de plusieurs threads UI : codeproject.com/Articles/64936/...
Vous devez vous connecter pour publier un commentaire.
Ce qui suit est une amélioration sur la mise en œuvre trouvés par Jonathan. Tout d'abord, il s'exécute à chaque gestionnaire d'événement sur le répartiteur associés avec elle plutôt que de supposer qu'ils sont tous sur le même (UI) répartiteur. Deuxièmement, il utilise BeginInvoke pour permettre de continuer le traitement pendant que nous attendons pour le répartiteur de devenir disponibles. Cela rend la solution beaucoup plus rapide dans les situations où le thread d'arrière-plan est de faire beaucoup de mises à jour avec traitement entre chacun d'entre eux. Peut-être plus important encore, il permet de surmonter les problèmes causés par le blocage lors de l'attente pour l'Invoquer (blocages peuvent se produire par exemple lors de l'utilisation de WCF avec ConcurrencyMode.Unique).
Parce que nous sommes à l'aide de BeginInvoke, il est possible que le changement ait été notifiée, est annulée avant que le gestionnaire est appelé. Ce serait normalement entraîner un "Index était hors de portée." exception levée lorsque les arguments de l'événement sont vérifiées par rapport à la nouvelle (modifié) l'état de la liste. Afin d'éviter cela, tous les retardée événements sont remplacés par Réinitialiser les événements. Cela pourrait provoquer un excès de redessiner dans certains cas.
Utilisation:
Invoke
résultats dans l'INTERFACE utilisateur de congélation. UtilisationBeginInvoke
à la place.Cette post par Bea Stollnitz explique que message d'erreur et pourquoi il est libellée de la façon dont il est.
EDIT: à Partir du Bea blog
Trouvé un.
http://www.julmar.com/blog/mark/2009/04/01/AddingToAnObservableCollectionFromABackgroundThread.aspx
dispatcher.Invoke
, c'est à dire faire quelque chose sur le thread GUI. Cela signifie deux choses: 1. le thread de s'arrêter et d'attendre pour l'interface graphique thread à chaque fois qu'il ajoute quelque chose à la collection. Les tâches de commutation est cher et à la diminution de la performance. 2. Le thread GUI pourrait étouffer dans la quantité de travail conduisant à l'absence de réponse de l'interface graphique. Un minuteur en fonction de la solution pour un problème similaire peut être trouvé ici stackoverflow.com/a/4530900/157224.Vous pouvez consulter également:
BindingOperations.EnableCollectionSynchronization
.Voir La mise à niveau .NET 4.5: Un ItemsControl est en contradiction avec les éléments de la source
Désolé, ne peut pas ajouter un commentaire, mais tout cela est faux.
ObservableCollection n'est pas thread-safe. Pas seulement à cause de ce répartiteur questions, mais ce n'est pas thread-safe à tous (à partir de msdn):
Regardez ici http://msdn.microsoft.com/en-us/library/ms668604(v=vs. 110).aspx
Il y a aussi un problème lors de l'appel de BeginInvoke avec un "Reset" de l'action. "Reset" est la seule action où le gestionnaire doit regarder la collection elle-même. Si vous BeginInvoke un "Reset" puis immédiatement BeginInvoke un couple de "Ajouter" les actions que gestionnaire d'accepter un "Reset" avec déjà mis à jour la collection et ensuite "Ajouter"de la volonté de créer du désordre.
Voici mon application qui fonctionne. En fait, je suis en train de penser de la suppression de BeginInvoke à tous:
Rapide, performant et thread-safe collection observable
Si vous souhaitez mettre à jour WPF INTERFACE utilisateur de Contrôler périodiquement et en même temps, utilisez l'INTERFACE utilisateur que vous pouvez utiliser DispatcherTimer.
XAML
C#
Aucun d'entre eux, il suffit d'utiliser Répartiteur.BeginInvoke
Essayez Ceci:
Voici une version de visual basic j'ai fait après quelques recherches sur google et légère mods. Fonctionne pour moi.
Petite erreur dans la version de visual basic. Il suffit de remplacer :
Par