2011-02-08 15 views
8

He buscado mucho, pero parece que no encuentro nada relacionado con mi problema específico.C# Aplicación de formularios de Windows - ¿Actualizando GUI desde otro hilo Y clase?

Quiero ser capaz de actualizar mi formulario MainUI de otra clase (SocketListener) y dentro de eso tengo un hilo que maneja la red (clientThread). Ahora mismo puedo ejecutar salidas simples desde el hilo de la red, como escribir en la salida del depurador y crear un MessageBox.

Pero lo que realmente quiero hacer es poder invocar el código del clienteThread que hará las cosas en mi instancia de MainUI. ¿Cómo puedo hacer esto?

Además, si alguien quiere partes específicas del código, entonces puedo publicarlo para ayudarlo a comprender mejor lo que estoy pidiendo.

¡Un cordial saludo!

Respuesta

17

Comprobar la InvokeRequired de la clase Control, y si es verdad, entonces llamar a la Invoke y pase un delegado (por lo general un método anónimo) que hace lo que quiere hacer en el subproceso del cliente.

Ejemplo:

public void DoWork(Form form) 
{ 
    if (form.InvokeRequired) 
    { 
     // We're on a thread other than the GUI thread 
     form.Invoke(new MethodInvoker(() => DoWork(form))); 
     return; 
    } 

    // Do what you need to do to the form here 
    form.Text = "Foo"; 
} 
+0

Dado que pertenezco a una clase diferente a la UI, ¿cómo obtengo la variable "forma" que apunta al formulario actualmente en ejecución para pasarlo a DoWork? –

+0

¿No sería bueno algún tipo de carátula sintáctica similar a AutoProperty? – MusiGenesis

+1

@firstEncounter: puede agregar un constructor a su clase que tome un 'Form' como parámetro, luego almacene la referencia en una variable de nivel de clase. – MusiGenesis

4

Sí, se puede añadir un constructor para la clase que toma la forma MainUI como parámetro. Esa es la manera rápida de hacerlo, pero introduce una dependencia "hacia atrás" de su clase a la MainUI donde, en teoría, no se requiere ninguna dependencia.

Como alternativa, sugeriría agregar un evento público a su clase al que el formulario de MainUI podría suscribirse. Cuando su clase necesita actualizar la MainUI (o los controles dentro de la MainUI), la clase simplemente "levantará" el evento. Esto llamará al método de MainUI que registró en el momento de la suscripción. Como ya es un método del formulario MainUI, todo lo que tiene que hacer es actualizar los controles apropiados en el formulario, asegurándose de tener en cuenta la propiedad InvokeRequired de cada control.

Y al hacer eso, aquí está la construcción que he estado usando en todo mi código.

class NetworkEventArgs : EventArgs { /* defined class here */ } 
private void NetworkEventHandler(object sender, NetworkEventArgs e) 
{ 
    Invoke((MethodInvoker) delegate { 
     myTextBox.Text = e.Message; 
    } 
} 

He basado esto en la entrada del blog here. No me ha fallado este enfoque, así que no veo ninguna razón para complicar mi código con una verificación recursiva de la propiedad InvokeRequired.

+0

Esta forma de estructurar mi código realmente funcionó bien para mí. Solo quiero agregar que tuve problemas con Invoke/MethodInvoker, mi GUI se cuelga. Lo cambié a BeginInvoke (nuevo MyDelegate (MyDelegateMethod), myParam); Funciona muy bien ahora. –

0

puede definir un evento de su clase clientThread

y manejarlo de MainForm cuando clientThread necesita MainForm consciente de hacer algo (como actualizar algún estatus de control) debe desencadenar el evento

por lo MainForm obtiene Parámetro del evento e invoca la función de actualización

Cuestiones relacionadas