Ver Mensaje Individual
  #2 (permalink)  
Antiguo 28/09/2007, 12:52
mhatter
 
Fecha de Ingreso: septiembre-2007
Mensajes: 52
Antigüedad: 17 años, 5 meses
Puntos: 2
Re: Manejo de hilos (threads)

Tu instinto inicial para usar hilos es correcto. Lo que sucede es que al trabajar con Windows.Forms e hilos hay que tener siempre en cuenta un detalle adicional, y es que cada control Windows.Forms está asociado con un hilo determinado, y todas las operaciones que realizan cambios visuales en los controles (como definir el texto de un label, agregar elementos a un ComboBox, etc) deben realizarse desde el hilo asociado con el control.

Esto quiere decir que cuando trabajas con un Form desde un hilo que tu creas (como ocurre con llecmb() en tu ejemplo), debes asegurarte de que tus operaciones en el Form se hagan desde el hilo del Form, y no desde el hilo nuevo.

Yo suelo confundirme también con este tipo de escenarios, así que si me permites quisiera extenderme un poco, usando una analogía, ya que me parece que ayuda a hacerse una idea de más o menos clara de cómo funciona todo esto.

Imaginemos que alguien le encarga la construcción de una casa a otra persona (seguramente una casa muy simple, para que una sola persona pueda construirla :). El cliente se reúne periódicamente con el constructor para explicarle los ajustes de la casa. Luego el constructor se pone a trabajar de la siguiente forma: anota todas las instrucciones (p.ej. dónde poner una ventana, qué color usar en las paredes, etc.) en hojas que coloca sobre su mesa de trabajo. Luego leyendo cada nota en orden, realiza las tareas que ahí se indican. Una vez termina limpia la mesa, es decir, bota todos los papeles pensando que ya no los necesita más. Después vuelve a tener otra reunión con el cliente y el ciclo se repite.

Ahora supongamos que el constructor decide conseguir un socio que asista a las reuniones con el cliente, para que él (el constructor) pueda seguir trabajando en la casa sin las interrupciones que implica reunirse con el cliente. Como verás, hasta aquí nuestra analogía se asemeja un poco al escenario de un programa que usa Windows.Forms con hilos (claro, una analogía no muy exacta, pero ilustrativa). El constructor representa el hilo que está asociado con el objeto Form que pinta los ComboBox y demás, y el socio representa el hilo que se encarga de ir llenando el ComboBox.

El problema entonces podría imaginarse de esta forma: si el socio anota las instrucciones del cliente, y las coloca sobre la mesa de trabajo del constructor, nada le garantiza que estas notas se lean y se cumplan, ya que mientras el socio coloca la nota en la mesa, el constructor puede estar trabajando, y cuando regrese a la mesa posiblemente la limpie, botando las notas nuevas.

Para evitar este problema, el socio podría hablar con el constructor y contarle las instrucciones que recibió del cliente para que el constructor mismo sea quien escriba las notas, las ponga en la mesa, y así garantiza que no se pierdan.


Bueno, con esa pequeña historia de lado, lo que resta decir es que en Windows.Forms para ejecutar cierto código desde el hilo del control (es decir, para hablar con el constructor, en lugar de poner las notas directamente en la mesa) se puede usar el método Invoke() de la clase Control. Tu ejemplo podría entonces verse algo así:

Código:
public void llecmb()
{
    this.pucTableAdapter.Fill(this.BaseDeDatosNuevaDat aSetPuc.puc);
}

private void trabajo_hilo ()
{
    Invoke(new MethodInvoker(llecmb));
}

//evento del boton
private void btnLlenar_Click(object sender, EventArgs e)
{
    ThreadStart delegadoPS = new ThreadStart(trabajo_hilo);
    try
    {
        //creacion del hilo
        hiloSecundario = new Thread(delegadoPS);
        //ejecucion del hilo
        hiloSecundario.Start();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}
No he probado el código, pero como ves, el ajuste consiste en usar Invoke() desde el método que corre en un hilo separado. Invoke() a su vez recibe como parámetro un Delegate que puede crearse con MethodInvoker.