2010-03-04 9 views
35

Sto costruendo un'applicazione WPF. Sto facendo alcune comunicazioni asincrone con il lato server, e io uso l'aggregazione di eventi con Prism sul client. Entrambe queste cose generano nuovi thread da generare che non sono il thread dell'interfaccia utente. Se provo a fare "operazioni WPF" su questi thread di callback e di gestione degli eventi, il mondo andrà in pezzi, cosa che ora ha iniziato a fare.Assicurarsi che le cose funzionino sul thread dell'interfaccia utente in WPF

Innanzitutto ho incontrato problemi nel tentativo di creare alcuni oggetti WPF nella richiamata dal server. Mi è stato detto che il thread doveva essere eseguito in modalità STA. Ora sto cercando di aggiornare alcuni dati dell'interfaccia utente in un gestore di eventi Prism e mi viene detto che:

Il chiamante non può accedere a questo thread perché ne possiede uno diverso.

Così; qual è la chiave per fare le cose bene in WPF? Ho letto su WPF Dispatcher in this MSDN post. Sto iniziando a prenderlo, ma non sono ancora un mago.

  1. È la chiave per utilizzare sempre Dispatcher.Invoke quando ho bisogno di eseguire qualcosa che non sono sicuro verrà chiamato sul thread dell'interfaccia utente?
  2. È importante se effettivamente è stato chiamato sul thread dell'interfaccia utente e faccio Dispatcher.Invoke comunque?
  3. Dispatcher.Invoke = in modo sincrono. Dispathcher.BeginInvoke = async?
  4. Will Dispatcher.Invoke richiede il thread dell'interfaccia utente e quindi si ferma per attendere? È una cattiva pratica e il rischio di programmi meno reattivi?
  5. Come si ottiene comunque il dispatcher? Dispatcher.CurrentDispatcher mi fornirà sempre il dispatcher che rappresenta il thread dell'interfaccia utente?
  6. Esisterà più di un Dispatcher o "Dispatcher" è sostanzialmente uguale al thread dell'interfaccia utente dell'applicazione?
  7. E qual è il problema con BackgroundWorker? Quando lo uso invece? Presumo che questo sia sempre asincrono?
  8. L'esecuzione di tutto ciò che viene eseguito sul thread dell'interfaccia utente (richiamato) avviene in modalità appartamento STA? Cioè se ho qualcosa che richiede di essere eseguito in modalità STA, Dispatcher.Invoke sarà sufficiente?

Qualcuno vuole cose clearify per me? Eventuali raccomandazioni correlate, ecc.? Grazie!

risposta

37

Andando oltre ciascuna delle vostre domande, una per una:

    Non
  1. abbastanza; dovresti invocare sul thread dell'interfaccia utente solo se necessario. Vedi # 2.
  2. Sì, importa. Non dovresti automaticamente solo Invoke tutto. La chiave è di invocare solo sul thread dell'interfaccia utente, se necessario. Per fare ciò, è possibile utilizzare il metodo Dispatcher.CheckAccess.
  3. Ciò è corretto.
  4. Anche corretto, e sì, si corre il rischio di programmi meno reattivi. La maggior parte delle volte, non si verificherà un grave calo di prestazioni (stiamo parlando di millisecondi per un interruttore di contesto), ma è necessario solo Invoke se necessario. Detto questo, in alcuni punti è inevitabile, quindi no, non direi che è una cattiva pratica. È solo una soluzione a un problema che incontrerai di tanto in tanto.
  5. In ogni caso che ho visto, ho fatto causa con Dispatcher.CurrentDispatcher. Per scenari complessi, questo potrebbe non essere sufficiente, ma io (personalmente) non li ho visti.
  6. Non del tutto corretto, ma questa linea di pensiero non farà alcun danno. Lasciatemelo dire in questo modo: il Dispatcherpuò essere utilizzato per accedere a il thread dell'interfaccia utente per l'applicazione. Ma non è di per sé il thread dell'interfaccia utente.
  7. BackgroundWorker viene generalmente utilizzato quando si utilizza un'operazione che richiede molto tempo e si desidera mantenere un'interfaccia utente reattiva durante l'esecuzione di tale operazione in background. Normalmente non usi BackgroundWorker invece di Invoke, piuttosto usi BackgroundWorker insieme a Invoke. Cioè, se hai bisogno di aggiornare qualche oggetto UI nel tuo BackgroundWorker, puoi richiamare sul thread dell'interfaccia utente, eseguire l'aggiornamento e quindi tornare all'operazione originale.
  8. Sì. Il thread UI di un'applicazione WPF, per definizione, deve essere eseguito in un apartment a thread singolo.

C'è molto da dire su BackgroundWorker, sono sicuro che molte domande sono già dedicati ad esso, quindi non voglio andare troppo profondità. Se sei curioso, controlla lo MSDN page for BackgroundWorker class.

+0

Grazie mille Charlie! Questo è davvero chiaro e utile! – stiank81

+0

Aggiunta una ottava domanda alla lista. Spero che tu possa aggiornare la tua risposta per includerla :-) – stiank81

+0

Haha- modificato per rispondere alla tua domanda finale. – Charlie

Problemi correlati