2010-05-13 3 views
4

J'ai le code suivant qui modifie une collection observable de 'screens' chaque fois qu'un utilisateur quitte.WPF: La modification de CollectionView à partir de Dispatcher continue de générer des erreurs

void OnUserLeft(int roomId, int userId, string username) 
    { 
     client.ClientDispatcher.Invoke(
      (Action<int>)((id) => 
      { 
       Console.WriteLine("Hello before the storm!"); 
       var screensToCheck = client.Screens.Where(s => s.CpuId == id).ToList(); 
       screensToCheck.Each(s => client.Screens.Remove(s)); 
       Console.WriteLine("Hello there!"); 
      }), userId); 
    } 

C'est enveloppé dans un appel à Dispatcher, soi-disant pour dépasser les problèmes de filetage liés à CollectionViews du client. Toutefois, je reçois toujours l'exception suivante:

Ce type de CollectionView ne prend pas en charge les modifications apportées à sa SourceCollection à partir d'un thread différent du thread Dispatcher.

Le répartiteur que vous voyez ci-dessus est défini dans MainViewModel de l'application WPF (nous utilisons MVVM), comme ceci:

public Dispatcher ClientDispatcher 
{ 
    get { return Dispatcher.CurrentDispatcher; } 
} 
+0

Qu'est-ce que c'est exactement "le répartiteur du client"? – Jon

+0

Désolé, ajouté un peu sur le 'ClientDispatcher' à la question. – Dusda

Répondre

6

De la documentation CurrentDispatcher:

gets la Dispatcher pour le thread en cours d'exécution et crée un nouveau Dispatcher si celui-ci n'est pas déjà associé au thread.

Il semble que vous accédez CurrentDispatchersans dans votre thread d'interface utilisateur, et en invoquant votre opération sur elle (c.-à-Invoke n'a pas d'effet du tout parce que le fil que vous êtes ne dispose pas d'un répartiteur; un nouveau est créé sur place et l'appel y va).

Vous devez sauvegarder la valeur de Dispatcher.CurrentDispatcher au moment où vous créez les Client instances (en supposant que vous faites que à partir du thread d'interface utilisateur), par exemple:

class Client { 
    Client() { 
     this.OwningDispatcher = Dispatcher.CurrentDispatcher; 
    } 

    Dispatcher OwningDispatcher { get; private set; } 
} 

Si vos Client instances ne sont pas créé sur le thread d'interface utilisateur, vous avez besoin d'un moyen d'obtenir la valeur correcte de Dispatcher sur eux.

+0

C'est la première fois que nous essayons de supprimer quelque chose, en utilisant le Dispatcher pour le faire. Donc vous dites que notre Dispatcher n'a probablement pas été implémenté correctement en premier lieu? Je vais essayer ça maintenant. – Dusda

+0

Succès! Vous monsieur, êtes brillants. – Dusda

+0

Je n'appellerais pas cela le résultat de la brillance. Je viens de lire la documentation pour les fonctionnalités que le code utilise avec soin. :-) – Jon

Questions connexes