Usando il C # Dispatcher

Sto creando un client di chat e non sono sicuro al 100% su come utilizzare il dispatcher . Quindi la domanda è che ho un metodo in quanto tale:

 public void LostConnection() { myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); } 

Devo rendere l’istruzione all’interno di (myGUI.chatBox... ) con Dispatcher.Invoke ? Apprezzo qualsiasi aiuto.

La tua app ha un thread principale dell’interfaccia utente (solitamente ManagedThreadId==1 ). Tipicamente in un’app di chat i tuoi eventi arriveranno su altri thread (sia thread di ascolto socket dedicato o thread di thread thread dal codice di ascolto). Se si desidera aggiornare l’interfaccia utente da un evento che viene triggersto su un altro thread, è necessario utilizzare il dispatcher. Un test utile qui è il metodo Dispatcher.CheckAccess() che restituisce true se il codice è sul thread dell’interfaccia utente e false se in qualche altro thread. Una chiamata tipica assomiglia a qualcosa:

 using System.Windows.Threading; // For Dispatcher. if (Application.Current.Dispatcher.CheckAccess()) { network_links.Add(new NetworkLinkVM(link, start_node, end_node)); } else { Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{ network_links.Add(new NetworkLinkVM(link, start_node, end_node)); })); } 

Se sei nella finestra principale puoi usare:

 Dispatcher.BeginInvoke(... 

Se ti trovi in ​​un altro contesto, ad esempio un modello di visualizzazione, utilizza:

 Application.Current.Dispatcher.BeginInvoke( 

Invoke vs BeginInvoke
Utilizzare Invoke se si desidera che il thread corrente attenda fino a quando il thread UI non ha elaborato il codice di invio o BeginInvoke se si desidera che il thread corrente continui senza attendere il completamento dell’operazione sul thread dell’interfaccia utente.

MessageBox, Dispatcher e Invoke / BeginInvoke:
Dispatcher.Invoke bloccherà il tuo thread fino a quando il MessageBox non verrà eliminato.
Dispatcher.BeginInvoke consentirà al codice thread di continuare a essere eseguito mentre il thread dell’interfaccia utente bloccherà la chiamata MessageBox fino alla sua rimozione.

CurrentDispatcher vs Current.Dispatcher!
Essere ware di Dispatcher.CurrentDispatcher poiché la mia comprensione di questo è che restituirà un Dispatcher per il thread corrente non il thread dell’interfaccia utente. Generalmente sei interessato al dispatcher sul thread dell’interfaccia utente – Application.Current.Dispatcher restituisce sempre questo.

Nota aggiuntiva:
Se stai riscontrando che devi controllare spesso il dispatcher CheckAccess, allora un utile metodo di supporto è:

 public void DispatchIfNecessary(Action action) { if (!Dispatcher.CheckAccess()) Dispatcher.Invoke(action); else action.Invoke(); } 

Che può essere chiamato come:

 DispatchIfNecessary(() => { network_links.Add(new NetworkLinkVM(link, start_node, end_node)); }); 

Qualcosa di simile (fuori dalla mia testa) dovrebbe funzionare:

 public void LostConnection() { myGUI.Invoke ((MethodInvoker)delegate { myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); }); }