C# do formantu uzyskiwany jest dostęp z wątku innego niż wątek, w którym został utworzony

0

Proste założenie: wyświetlać przychodzące przez UART z mikrokontrolera dane i wyświetlać na richTextBox, aby zachować "historię" danych.

        
        string sdata;
        string temp;
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                sdata = serialPort1.ReadExisting();
                temp = rtbDisplay.Text;
                rtbDisplay.Text = sdata + "\n" + temp;
            }
            catch(Exception ex) { MessageBox.Show(ex.Message,"Exception",MessageBoxButtons.OK,MessageBoxIcon.Exclamation,MessageBoxDefaultButton.Button1); }
        }

Po uruchomieniu na dzień dobry error: Nieprawidłowa operacja między wątkami: do formantu 'rtbDisplay' uzyskiwany jest dostęp z wątku innego niż wątek, w którym został utworzony.

Udało mi się to obejść timerem sczytując dane ze zmiennej sdata co 500ms, ale nie na tym to polega.
Nie mam doświadczenia z wielowątkowością w C#... nie wiem przyznanie dostępu dla innych wątków?

2

InvokeRequired, Invoke

0
        string sdata;
        string temp;
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                sdata = serialPort1.ReadExisting();

                this.Invoke(
                    new Action(() => 
                                    {
                                        temp = rtbDisplay.Text;
                                        rtbDisplay.Text = sdata + "\n" + temp;
                                    }));
            }
            catch (Exception ex) { if (InvokeRequired) MessageBox.Show("dupa", "duopa"); MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); }
        }

Podziękował :)

1

eee... komplikujesz.

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    if (InvokeRequired)
        Invoke(serialPort1_DataReceived, sender, e);
    else
    {
        sdata = serialPort1.ReadExisting();
        temp = rtbDisplay.Text;
        rtbDisplay.Text = sdata + "\n" + temp;
    }
}

nie sprawdzane, ale chodzi o zasadę: Invoke wywołuje rekurencyjnie tę samą metodę, a wtedy InvokeRequired już będzie false i wykona się kod pod else.

1 użytkowników online, w tym zalogowanych: 0, gości: 1