chasher
chasher

Reputation: 149

Display serial in to textbox - Cross thread operation

I want to receive a serial string and display in a textbox, I posted a question yesterday about using the background worker, I got lots of help thanks, but still couldn't solve it. So I started a new simplest project that I could: Form 1 has a textbox to display return value, 1 button to connect com port, 1 button to send serial out. When device on com port receives the ? sent, it returns a string which I want to display in the textbox tbEncoderValue. Serial coms handled by SerialPortClass. In SetText is where the error occurs. What is the best & simplest way of writing to this textbox please?

Form1: EDIT Minimised verion posted

namespace TestSensor
{
    public partial class Form1 : Form
    {
        public static TextBox tbE = new TextBox();

        // create a SerialPortClass object variable and called it sp
        SerialPortClass sp = new SerialPortClass();      

        public Form1()
        {
            InitializeComponent();
            tbEncoderValue.Text = "0000";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            tbE = tbEncoderValue;
        }
   }
}

SerialPortClass:

namespace TestSensor
{
    public class SerialPortClass : Form
    {

        internal delegate void SerialDataReceivedEventHandlerDelegate(
                 object sender, SerialDataReceivedEventArgs e);

        string InputData = String.Empty;

        public SerialPortClass()
        {
            serialPort1.DataReceived += 
                  new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
        }

        private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
        {
            Console.WriteLine("Data recieved");
            InputData = serialPort1.ReadExisting();
            if (InputData != String.Empty)
            {
                SetText(InputData);
            }
        }

        public void SetText(string text)
        {
            Console.WriteLine("set text");
            Console.WriteLine(text);
            Form1.tbE.Text = text; //causes cross thread operation error here
        }

      }
}


Form1.tbE.Text = text; //causes cross thread operation error here

After reading @Pavieł Kraskoŭski comment again, I've now got when serial received to InvokeMethod and display a fixed string, but would you pass string variable in please?

        public delegate void InvokeDelegate();

        public void SetText(string text)
        {
            Console.WriteLine("set text");
            Console.WriteLine(text);

            Form1 fm = new Form1();

            Form1.tbE.BeginInvoke(new InvokeDelegate(InvokeMethod));

        }

        public void InvokeMethod()
        {
            Form1.tbE.Text = "Executed delegate";
        }

Upvotes: 2

Views: 666

Answers (2)

Baddack
Baddack

Reputation: 2053

You can use the method invoker delegate and set the text in your setText method.

this.Invoke((MethodInvoker)delegate{ tbE.Text = textToDisplay; });

or from your code:

public void SetText(string text)
{
    Form1 fm = new Form1();

    Console.WriteLine("set text");
    Console.WriteLine(text);
    textToDisplay = text;
    fm.Invoke((MethodInvoker)delegate{ tbE.Text = textToDisplay; });    
}

Upvotes: 1

chasher
chasher

Reputation: 149

With thanks to @Paviel I know have: which works, but I don't think using a class variable is the best way of passing string into the InvokeMethod, any comments please?

public delegate void InvokeDelegate();

private string textToDisplay;

public void SetText(string text)
{
    Form1 fm = new Form1();

    Console.WriteLine("set text");
    Console.WriteLine(text);
    textToDisplay = text;
    Form1.tbE.BeginInvoke(new InvokeDelegate(InvokeMethod));     
}

public void InvokeMethod()
{
    Form1.tbE.Text = textToDisplay;
}

Upvotes: 0

Related Questions