Comunicaciones serie C#

Estoy escribiendo una aplicación C# para comunicarme en serie con un microcontrolador. Tengo algunas preguntas sobre cómo manejar los mensajes recibidos. A continuación se muestra el código que estoy usando en este momento. Recibió los mensajes perfectamente bien, pero no puedo actualizar el formulario ni almacenar los datos en ningún lugar fuera de este método (porque está en otro hilo).

com.DataReceived += new SerialDataReceivedEventHandler(OnReceived);


public void OnReceived(object sender, SerialDataReceivedEventArgs c) // This is started in another thread...
    {
        com.DiscardOutBuffer();
        try
        {
            test = com.ReadExisting();
            MessageBox.Show(test);       
        }
        catch (Exception exc) 
        {
            MessageBox.Show(exc.ToString());
        }
    }

Cuando intento modificar el formulario o llamar a otro método desde aquí, este es el mensaje de error que recibo: "La operación Cross Thead no es válida".

Me gustaría poder mostrar la información en otro lugar o, mejor aún, colocarla en una matriz para luego almacenarla como un archivo. ¿Hay alguna manera de que pueda hacer esto?

Gracias de nuevo!

preguntado el 02 de enero de 13 a las 19:01

2 Respuestas

Necesita invocar en el hilo principal usando Invoke or BeginInvoke:

public void OnReceived(object sender, SerialDataReceivedEventArgs c)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new EventHandler<SerialDataReceivedEventArgs>(OnReceived), sender, c);
        return;
    }

    com.DiscardOutBuffer();
    try
    {
        test = com.ReadExisting();
        MessageBox.Show(test);       
    }
    catch (Exception exc) 
    {
        MessageBox.Show(exc.ToString());
    }
}

O puede factorizar parte del controlador de eventos (como mostrar un cuadro de mensaje) e invocarlo en su lugar.

Respondido el 02 de enero de 13 a las 19:01

Esto funcionó perfectamente, ¡gracias! ¿Qué logra invocar? - Bubón

@VRKnight le dice al subproceso principal (GUI) que ejecute su código, en lugar del subproceso de fondo. Solo el subproceso de la GUI puede modificar la GUI (por ejemplo, mostrando un cuadro de mensaje), por lo que esto es necesario. - Jon B

El problema que tiene es que está intentando actualizar la interfaz de usuario desde un subproceso que no es de interfaz de usuario. Lo que tienes que hacer es invocar tu MessageBox llama al subproceso de la interfaz de usuario.

Algo como:

public void OnReceived(object sender, SerialDataReceivedEventArgs c) // This is started in another thread...
{
    com.DiscardOutBuffer();
    try
    {
        test = com.ReadExisting();
        SetValue(test);       
    }
    catch (Exception exc) 
    {
        SetValue(exc.ToString());
    }
}


delegate void valueDelegate(string value);

private void SetValue(string value)
{   
    if (this.InvokeRequired)
    {
        this.Invoke(new valueDelegate(SetValue),value);
    }
    else
    {
        MessageBox.Show(value);
    }
}

Respondido el 02 de enero de 13 a las 19:01

Ambas respuestas funcionan, ¿qué significa exactamente Invocar? - Bubón

Aquí hay una pequeña lectura al respecto, pero básicamente, significa ejecutar el código solicitado en el subproceso que posee o pertenece el control de la interfaz de usuario. Técnicamente, PUEDE hacer lo que quiera sin invocar (deshabilitando una configuración del depurador), pero no es seguro, por lo que la invocación garantiza la ejecución adecuada en todos los subprocesos. msdn.microsoft.com/en-us/library/zyzhdc6b.aspx - conceder h

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