2
votes

I'm trying to make a chat with serial port communication. This chat has to have an interface in a WPF Project, I already made my interface and everything. I'm stuck in receiving the response through the serial port. I already tried adding a DataReceived event from the serial port but I'm afraid I'm using it wrong since I have never programmed in C# before. It is a really simple code. What I need to do is receive the information from the serial port and display it in a text block as it would look in a simple chat window.

        InitializeComponent();
        _serialPort = new SerialPort();

        foreach (string s in SerialPort.GetPortNames())
        {
            listaComs.Items.Add(s);
        }


    }

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        visor.Inlines.Add("Data Received:");
        visor.Inlines.Add(indata);
    }
    private void enviarClick(object sender, RoutedEventArgs e)
    {
        _serialPort.WriteLine(escribir.Text);
        visor.Inlines.Add("Yo: " + escribir.Text + Environment.NewLine);
    }

    private void cambiarTexto(object sender, MouseButtonEventArgs e)
    {
        if (escribir.Text == "Escriba su texto")
        {
            escribir.Text = "";
        }
    }

    private void inicializarSerial()
    {
        // Poner las propiedades correctas.
        _serialPort.BaudRate = 9600;
        _serialPort.Parity = Parity.None;
        _serialPort.StopBits = StopBits.One;
        _serialPort.DataBits = 8;
        _serialPort.Handshake = Handshake.None;
        _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        // Poner los timeouts de escritura y lectura
        _serialPort.ReadTimeout = 500;
        _serialPort.WriteTimeout = 500;
    }

    private void conectarCom(object sender, RoutedEventArgs e)
    {
        string seleccion = listaComs.SelectedItem.ToString();
        _serialPort.PortName = seleccion;
        inicializarSerial();
        _serialPort.Open();
        _continue = true;
        visor.Text = "";
    }

    private void desconectarCom(object sender, RoutedEventArgs e)
    {
        _serialPort.Close();
    }

When I run this in the .exe file it crashes down with an InvalidOperationException with inner exception (translated):

"The subprocess that realized the call cannot gain Access to this object because the propietary is another subprocess."

1
Can you post the text of the error or does it crash without giving an error? - orgtigger
If it is "without error" make sure your debugger is attached so you can see the actual exception. - BradleyDotNET
It crashes without giving an error but a debug option. When I hit debug it says an InvalidOperationException wasn't controlled. As additional information it says: "The subprocess that realized the call cannot gain Access to this object because the propietary is another subprocess." That happens when the serial port is supposed to recieve information. - Kassandra Hinojosa Rodriguez
Where can I find the InnerException? When I click debug it opens Visual Studio but I don't know about the InnerException. - Kassandra Hinojosa Rodriguez
I think something was lost in translation there. Is this a cross-thread invocation issue? If you click "View more" (or something like that) in the exception dialog, you can see the inner exception. Looking at your code, I'm pretty sure this is a cross-thread issue. - BradleyDotNET

1 Answers

1
votes

Events are fired from the thread that invoked them, and in the case of a serial port (or any comms layer), this is going to definitely not be on the UI thread.

However, UI operations must be done on the UI thread. So the code below will fail:

    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    visor.Inlines.Add("Data Received:");
    visor.Inlines.Add(indata);

Because you are modifying a UI element from the wrong thread. The solution is to use BeginInvoke (MSDN) to marshal the operation onto the UI thread:

    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();

    Dispatcher.BeginInvoke(() =>
    {
       visor.Inlines.Add("Data Received:");
       visor.Inlines.Add(indata);
    }, null);

PS. The translation of your exception didn't seem right; if this was the issue, the exception you will see is (in English):

Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on.

(Or something very similar). I didn't recognize the provided text, and given your code, it looks like this is what you encountered.