Buscar..


Accediendo a los controles de formulario desde otros hilos.

Si desea cambiar un atributo de un control, como un cuadro de texto o una etiqueta de otro hilo que no sea el hilo de la GUI que creó el control, deberá invocarlo o, de lo contrario, podría aparecer un mensaje de error que indique:

"Operación de subprocesos no válida: control 'nombre_control' al que se accede desde un hilo que no sea el hilo en el que se creó."

El uso de este código de ejemplo en un formulario system.windows.forms emitirá una excepción con ese mensaje:

private void button4_Click(object sender, EventArgs e)
{
    Thread thread = new Thread(updatetextbox);
    thread.Start();
}

private void updatetextbox()
{
    textBox1.Text = "updated"; // Throws exception
}

En cambio, cuando desea cambiar el texto de un cuadro de texto dentro de un hilo que no lo posee, use Control.Invoke o Control.BeginInvoke. También puede usar Control.InvokeRequired para verificar si es necesario invocar el control.

private void updatetextbox()
{
    if (textBox1.InvokeRequired)
        textBox1.BeginInvoke((Action)(() => textBox1.Text = "updated"));
    else
        textBox1.Text = "updated";
}

Si necesita hacer esto a menudo, puede escribir una extensión para objetos invocables para reducir la cantidad de código necesario para realizar esta comprobación:

public static class Extensions
{
    public static void BeginInvokeIfRequired(this ISynchronizeInvoke obj, Action action)
    {
        if (obj.InvokeRequired)
            obj.BeginInvoke(action, new object[0]);
        else
            action();
    }
}

Y actualizar el cuadro de texto desde cualquier hilo se vuelve un poco más simple:

private void updatetextbox()
{
    textBox1.BeginInvokeIfRequired(() => textBox1.Text = "updated");
}

Tenga en cuenta que Control.BeginInvoke como se usa en este ejemplo es asíncrono, lo que significa que el código que viene después de una llamada a Control.BeginInvoke se puede ejecutar inmediatamente después, ya sea que el delegado pasado se haya ejecutado o no.

Si necesita asegurarse de que textBox1 se actualice antes de continuar, use Control.Invoke en su lugar, lo que bloqueará el subproceso de llamada hasta que se haya ejecutado su delegado. Tenga en cuenta que este enfoque puede ralentizar significativamente su código si realiza muchas llamadas de invocación y tenga en cuenta que bloqueará su aplicación si su hilo de GUI está esperando a que el hilo de llamada se complete o libere un recurso retenido.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow