2009-08-11 11 views
6

J'ai un thread qui appelle un objet qui obtient des choses à partir d'Internet. Lorsque cet objet est rempli avec toutes les informations requises, il déclenche un événement avec un objet toutes les informations. L'événement est consommé par le contrôleur qui a démarré le thread.Thread WPF et GUI comment accéder à l'objet à partir de thread différent?

L'objet renvoyé par l'événement est ajouté à une collection qui est liée à l'interface graphique via une approche de modèle de vue.

Le problème est que je ne peux pas utiliser CheckAccess avec la liaison ... comment puis-je résoudre le problème d'utilisation de l'objet qui a été créé à partir d'un autre thread de la principale?

L'erreur que je reçois quand j'ajoute l'objet à la collection du fil principal est:

Ce type de CollectionView ne supporte pas les changements à son SourceCollection d'un fil différent du fil Dispatcher.

Ce contrôleur le:

public class WebPingerController 
{ 
    private IAllQueriesViewModel queriesViewModel; 

    private PingerConfiguration configuration; 

    private Pinger ping; 

    private Thread threadPing; 

    public WebPingerController(PingerConfiguration configuration, IAllQueriesViewModel queriesViewModel) 
    { 
     this.queriesViewModel = queriesViewModel; 
     this.configuration = configuration; 
     this.ping = new Pinger(configuration.UrlToPing); 
     this.ping.EventPingDone += new delPingerDone(ping_EventPingDone); 
     this.threadPing = new Thread(new ThreadStart(this.ThreadedStart)); 
    } 


    void ping_EventPingDone(object sender, QueryStatisticInformation info) 
    { 
     queriesViewModel.AddQuery(info);//ERROR HAPPEN HERE 
    } 

    public void Start() 
    { 
     this.threadPing.Start(); 
    } 

    public void Stop() 
    { 
     try 
     { 
      this.threadPing.Abort(); 
     } 
     catch (Exception e) 
     { 

     } 
    } 

    private void ThreadedStart() 
    { 
     while (this.threadPing.IsAlive) 
     { 
      this.ping.Ping(); 
      Thread.Sleep(this.configuration.TimeBetweenPing); 
     } 
    } 
} 

Répondre

6

J'ai trouvé la solution sur ce blog. Au lieu de simplement appeler la collection pour ajouter l'objet à partir du thread.

queriesViewModel.AddQuery(info); 

Je dois passer le fil principal au contrôleur et utiliser le répartiteur. La réponse du garde était très proche.

public delegate void MethodInvoker(); 
    void ping_EventPingDone(object sender, QueryStatisticInformation info) 
    { 
     if (UIThread != null) 
     { 

      Dispatcher.FromThread(UIThread).Invoke((MethodInvoker)delegate 
      { 
       queriesViewModel.AddQuery(info); 
      } 
      , null); 
     } 
     else 
     { 
      queriesViewModel.AddQuery(info); 
     } 
    } 
+1

Pouvez-vous poster la définition de UIThread dans ce contexte s'il vous plaît? Merci. Je ne sais pas quoi remplacer avec dans mon code – Para

+1

Même question. Que signifie UIThread exactement? – zero51

+0

Cela devrait être une sous-classe de 'System.Windows.Threading.DispatcherObject'. – Jalal

3

une solution pourrait être d'initialiser l'objet sur le thread principal?

MyObject obj; 

this.Dispatcher.Invoke((Action)delegate { obj = new MyObject() }); 

Modifier: Lors d'une deuxième lecture à travers, ce qui est probablement pas une solution compte tenu de votre modèle. Recevez-vous une erreur d'exécution telle quelle? Si l'objet que vous transmettez est le vôtre, assurez-vous que l'objet est sûr pour les threads, ce qui rendrait CheckAccess inutile.

+0

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

Questions connexes