¿Por qué usar Action en este código?

Hola, veo el siguiente código:

void UpdateMessage (string message)
{
    Action action = () => txtMessage.Text = message;
    this.Invoke (action);
}

¿Por qué utilizar Action y luego invocar la acción aquí? ¿Por qué no usar txtMessage.Text = message reemplazar el código en el cuerpo de la función?


Noticias

Una versión más completa del código, presentada en un comentario, reproducida a continuación con resaltado de sintaxis, sangría, etc.

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
        InitializeComponent(); 
        new Thread(Work).Start(); 
    } 

    void Work() 
    { 
        Thread.Sleep(5000); 
        UpdateMessage("My Garden"); 
    } 

    void UpdateMessage(string message) { 
        Action action = () => textBox1.Text = message; 
        this.Invoke(action); 
    } 
} 

preguntado el 10 de mayo de 11 a las 13:05

Creo que con lo que ha tropezado es con lo que en el negocio llamamos "código incorrecto". Es posible que se haya copiado de algún lugar del sistema que realmente necesitaba una dirección indirecta. Pero tienes toda la razón. Esto no lo hace. -

@Axeman ¿Cómo puede saber por el código proporcionado que UpdateMessage siempre se ejecuta en el hilo de la GUI? -

@Axeman, esto no es un "código incorrecto", es una invocación de subproceso de interfaz de usuario. -

No confundir con una llamada action.Invoke () -

@David Heffernan, bueno, eso es lo único que contemplé. Pero no había nada allí específicamente que dijera que este es un código GUI, y siempre que lo sea, y siempre que la actualización del Text campo es tan laborioso o peligroso como hilo de fondo, ¿por qué diablos el componente no ha elegido una forma segura / correcta? sí mismo? Sigue siendo un código tonto, ya sea que sea endémico o no. -

3 Respuestas

Debido a que este código se ejecuta en un subproceso diferente al de la interfaz de usuario y debe combinarse con el subproceso de la interfaz de usuario con Invoke.

La documentación esperando Control.Invoke() establece lo siguiente:

Ejecuta el delegado especificado en el subproceso que posee el identificador de ventana subyacente del control.

Todo esto es necesario porque el marco de Windows subyacente requiere que las operaciones en un identificador de ventana sean realizadas por el subproceso que posee el identificador de ventana.

contestado el 10 de mayo de 11 a las 17:05

Si se llama a UpdateMessage desde otro hilo, debe invocar al hilo principal para interactuar con los elementos de la GUI

Si usa solo txtMessage.Text = message conseguirás CrossThreadOperationException

contestado el 10 de mayo de 11 a las 17:05

Sí, este UpdateMessage se invoca en otro hilo que no sea el hilo principal de la interfaz de usuario. Pero, ¿por qué uso txtMessage.Text = message y no vi la excepción que se supone que está allí? ¡Gracias! - spspli

Debe trabajar con las propiedades de un control en el subproceso de la interfaz de usuario, de lo contrario, recibirá una excepción.

Control.Invoke () ejecutará su delegado enviando un mensaje de Windows al bucle de mensajes de la ventana.

Pero puede optimizar el código para evitar la sincronización innecesaria de subprocesos cuando no es necesario:

void UpdateMessage (string message)
{
    if(InvokeRequired)
    {
        Invoke((Action)()=>UpdateMessage(message));
        return;
    }

    txtMessage.Text = message;
}

contestado el 10 de mayo de 11 a las 18:05

usando el sistema; utilizando System.Collections.Generic; using System.ComponentModel; utilizando System.Data; usando System.Drawing; utilizando System.Linq; usando System.Text; usando System.Windows.Forms; usando System.Threading; espacio de nombres TestAction {Form1 público de clase parcial: Form {Form1 público () {InitializeComponent (); nuevo hilo (Trabajo) .Start (); } void Work () {Thread.Sleep (5000); UpdateMessage ("Mi jardín"); } void UpdateMessage (mensaje de cadena) {Action action = () => textBox1.Text = message; this.Invoke (acción); }}} - spspli

En este código, llama al método UpdateMessage desde el hilo que se inició desde el constructor. La llamada Control.Invoke () es necesaria en el escenario actual. - Viacheslav Smityukh

¡Gracias! Sé que esto es necesario ahora. Pero me pregunto por qué si no lo uso, no vi ninguna excepción. - spspli

Intente iniciarlo en el depurador, debería ver esa excepción. - Viacheslav Smityukh

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.