Garantire che le cose funzionino sul thread dell’interfaccia utente in WPF

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.

Per prima cosa 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é lo possiede un thread diverso.

Così; qual è la chiave per fare le cose bene in WPF? Ho letto su WPF Dispatcher in questo post MSDN . 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. Importa se effettivamente è stato chiamato sul thread dell’interfaccia utente e faccio Dispatcher.Invoke comunque?
  3. Dispatcher.Invoke = in modo sincrono. Dispathcher.BeginInvoke = async?
  4. Dispatcher.Invoke richiede il thread dell’interfaccia utente e quindi si ferma per attendere? È una ctriggers pratica e il rischio di programmi meno reattivi?
  5. Come faccio ad avere lo speditore comunque? 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. Tutto ciò che viene eseguito sul thread dell’interfaccia utente (invocato) verrà eseguito in modalità appartamento STA? Ad esempio, se ho qualcosa che richiede di essere eseguito in modalità STA, Dispatcher.Invoke sarà sufficiente?

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

Passando su ciascuna delle tue domande, una per una:

  1. Non proprio; dovresti invocare sul thread dell’interfaccia utente solo se necessario. Vedi # 2.
  2. Sì, importa. Non dovresti semplicemente Invoke automaticamente tutto. La chiave è di invocare solo sul thread dell’interfaccia utente, se necessario. Per fare ciò, è ansible utilizzare il metodo Dispatcher.CheckAccess .
  3. È corretto.
  4. Anche corretto, e sì, si corre il rischio di programmi meno reattivi. Nella maggior parte dei casi, 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 ctriggers 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. Consentitemi di metterlo in questo modo: il Dispatcher può essere usato per ottenere l’accesso al thread dell’interfaccia utente per l’applicazione. Ma non è di per sé il thread dell’interfaccia utente.
  7. BackgroundWorker viene generalmente utilizzato quando si richiede un’operazione dispendiosa in termini di tempo e si desidera mantenere un’interfaccia utente retriggers durante l’esecuzione di tale operazione in background. Normalmente non usi BackgroundWorker invece di Invoke, piuttosto usi BackgroundWorker in congiunzione con Invoke. Cioè, se hai bisogno di aggiornare qualche object 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à dedicate ad esso, quindi non entrerò troppo in profondità. Se sei curioso, controlla la pagina MSDN per la class BackgroundWorker .