2011-10-20 27 views
16

Estoy construyendo un cliente de chat y no estoy 100% seguro de cómo usar el dispatcher. Así que la pregunta es que tengo un método como tal:Usando C# Dispatcher

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

¿Es necesario que la declaración surrond dentro (myGUI.chatBox...) con un Dispatcher.Invoke? Agradezco cualquier ayuda.

+0

Eso Depende ... ¿En qué hilo se ejecuta ese método? Además, solo para estar seguro, estás usando WPF, ¿verdad? ('Dispatcher' solo funciona con eso.) – svick

+1

¿Qué marco de interfaz de usuario está usando?(WinForms, WPF o SL) Existen diferencias entre ellos –

+0

Sí, como sugiere svick, depende de si está tocando su UI desde otro hilo (asincrónicamente) – gideon

Respuesta

68

Su aplicación tiene un hilo principal interfaz de usuario (por lo general ManagedThreadId==1). Por lo general, en una aplicación de chat sus eventos aparecerán en otros hilos (ya sea hilos de escucha de socket dedicado o hilos de grupo de hilos desde el código de escucha). Si desea actualizar la interfaz de usuario de un evento que obtiene algún otro hilo, debe usar el despachador. Una prueba útil aquí es el método Dispatcher.CheckAccess() que devuelve verdadero si el código está en el hilo de UI y falso si está en algún otro hilo. Una llamada típica se ve algo como:

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

Si estás en la ventana principal se puede utilizar:

Dispatcher.BeginInvoke(... 

Si estás en someother contexto por ejemplo, un modelo de vista a continuación, utilizar:

Application.Current.Dispatcher.BeginInvoke( 

invocación vs BeginInvoke
uso Invoke si desea que el hilo actual que esperar hasta que el hilo de interfaz de usuario ha procesado el código de envío o BeginInvoke si desea que el hilo actual continúe sin esperar a que la operación finalice en el hilo de la interfaz de usuario.

de mensaje, despachadores e invocar/BeginInvoke:
Dispatcher.Invoke bloqueará el hilo hasta que se desestimó el cuadro de mensaje.
Dispatcher.BeginInvoke permitirá que su código de subproceso continúe ejecutándose mientras que el subproceso de la interfaz de usuario se bloqueará en la llamada de MessageBox hasta que se desestime.

CurrentDispatcher versus Current.Dispatcher!
Tenga en cuenta Dispatcher.CurrentDispatcher ya que mi comprensión de esto es que devolverá un despachador para el hilo actual, no el hilo de la interfaz de usuario. Generalmente está interesado en el despachador en el hilo de la interfaz de usuario: Application.Current.Dispatcher siempre lo devuelve.

Nota adicional:
Si usted está encontrando que está teniendo para comprobar despachador CheckAccess a menudo entonces un método de ayuda útil es:

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

que puede ser llamado como:

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

Hola chicos, lo siento, no especifiqué, sí, es una aplicación de wpf y sí, es cross threading. Estoy configurando el delegado en el backend que luego alerta a mi modelo, que luego llamará a ese método de despacho y actualizará la interfaz de la interfaz gráfica de usuario. Todavía no tengo una opción con intellesense para agregar un despachador, pero intentaré forzarlo y ver si se ejecuta. ¡Gracias chicos! ¿Algún otro consejo? – Tombo890

+0

Si ha incluido el uso de la declaración y utiliza Application.Current.Dispatcher, debería obtener un resultado. Si su "back-end" está en una DLL, entonces necesitará pasar el DHI Dispatcher de la interfaz de usuario a su objeto allí para que pueda hacer referencia a él. – Ricibob

+0

@Ricibob, solo para ser quisquilloso, creo que el hilo de UI no siempre tiene que tener Id de 1. – svick

2

Algo como esto (la parte superior de la cabeza) debería funcionar:

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

Eso estaría en WinForms. Esta pregunta es aparentemente sobre WPF. – svick

+1

Sí. Eso no fue obvio a partir de la pregunta. –

Cuestiones relacionadas