2009-08-11 12 views
6

Ho una discussione che chiama un oggetto che ottiene alcune informazioni da Internet. Quando questo oggetto è riempito con tutte le informazioni richieste, solleva un evento con un oggetto fornirà tutte le informazioni. L'evento viene consumato dal controller che ha avviato il thread.Thread WPF e GUI come accedere all'oggetto da thread diversi?

L'oggetto restituito dall'evento è aggiunto in una raccolta che è vincolata alla GUI tramite un approccio di modello di vista.

Il problema è che non posso usare CheckAccess con il binding ... come posso risolvere il problema dell'utilizzo di Object che è stato creato da un altro thread di quello principale?

L'errore che ricevo quando aggiungo l'oggetto alla raccolta del filo principale è:

Questo tipo di CollectionView non supporta le modifiche alla sua SourceCollection da un filo diversi dal thread dispatcher.

Questo il controllore:

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); 
     } 
    } 
} 

risposta

6

Ho trovato la soluzione su questo blog.

Invece di chiamare la raccolta per aggiungere l'oggetto dalla discussione.

queriesViewModel.AddQuery(info); 

Devo passare il thread principale al controller e utilizzare il dispatcher. La risposta della guardia era molto vicina.

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

Puoi pubblicare la definizione di UIThread in questo contesto, per favore? Grazie. Non so cosa sostituirlo con il mio codice – Para

+1

Stessa domanda. Che cosa significa esattamente UIThread? – zero51

+0

Dovrebbe essere una sottoclasse di 'System.Windows.Threading.DispatcherObject'. – Jalal

3

Potrebbe essere una soluzione per inizializzare l'oggetto sul thread principale?

MyObject obj; 

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

Edit: Ad una seconda lettura attraverso, questo probabilmente non è una soluzione dato il vostro modello. Stai ricevendo un errore di runtime così com'è? Se l'oggetto che stai passando indietro è il tuo, assicurarti che l'oggetto sia sicuro per i thread potrebbe rendere CheckAccess inutile.

+0

Questo tipo di CollectionView non supporta le modifiche a SourceCollection da un thread diverso dal thread Dispatcher. –

Problemi correlati