C# GuiUpdateThread: Refrescar el contenido de la ventana desde un subproceso

En ocasiones cuando desarrollamos aplicaciones de ventanas es necesario desarrollar un proceso largo, si lo hacemos de la forma clásica puede suceder que la interfaz se bloquee, lo ideal en estos casos lo ideal es usar subprocesos.

Vamos a emplear una clase Thread para actualizar el contenido de un campo de edición en un formulario. El thread arranca cuando pulsamos un botón y activa un contador de 0 a 100 con un Sleep en cada ejecución del bucle, cada iteración refresca el contenido del campo de edición con el valor del contador.

t1

Controles:

  • btnStartThread: Botón con leyenda “&StartThread” y diseño plano, cuando hacemos clic sobre el desencadena el evento btnStartThread_Click que ejecuta el subproceso txtNumUpdateThread.
  • txtNum: Campo de edición deshabilitado (Enabled=False).

Cuando pulsamos el botón programamos el arranque del evento:

t2

Un hilo es una instancia de la clase Thread, al crear la instancia debemos pasar como parámetro al constructor la instancia de un delegado (ThreadStart), el delegado apunta al método que corre en segunda plano actualizando el contenido del campo de edición txtNum (txtNumUpdateThread).

Ahora creamos el método txtNumUpdateThread, este será el encargado de refrescar el contenido del campo de edición:

t3

Cuando tenemos actualizar un componente del interfaz gráfico desde un método en un hilo separado en vez de escribir simplemente:

txtNum.Text = x.ToString();

Debemos usar el método Invoke del control (la propiedad InvokeRequired del control contiene true si debemos usar un método de invocación).

“El acceso a los controles de Windows Forms no es intrínsecamente seguro para subprocesos. Si tiene dos o más subprocesos que manipulan el estado de un control, es posible que este acabe teniendo un estado incoherente”

Podemos comprobarlo añadiendo algo de código a la función anterior:

t4

 

GuiUpdateThread2: Segundo ejemplo


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Threading;

namespace GuiUpdateThread2
{
public partial class Form1 : Form
{
// delegado con la misma firma del método
public delegate void UpdateTextCallback(string msg);

public Form1()
{
InitializeComponent();
}

private void UpdateTxtMsg(string StrMsg)
{
TxtMsg.Text = StrMsg;
}

private void UpdateTxtThread()
{
string StrTxt = "Texto generado desde otro hilo.";
if (TxtMsg.InvokeRequired)
{
TxtMsg.Invoke(new UpdateTextCallback(this.UpdateTxtMsg),
new object[] { StrTxt });
}
else
{
TxtMsg.Text = StrTxt;
}
}

private void button1_Click(object sender, EventArgs e)
{
ThreadStart delegado = new ThreadStart(UpdateTxtThread);
Thread hilo = new Thread(delegado);
hilo.Start();
}
}
}

 

Posts en este blog:

Enlaces externos:

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s