Vzinik
Vzinik

Reputation: 11

How to display data from another on UI thread

I am working on a winforms application that plots live data from a tcp/ip connection. I am taking input from a thread (let's say input thread) and storing it as a .csv file which is then used to plot the graph with a button press and am able to do so.

I am having a problem with showing messages on a listbox about the input data I am getting from the input thread. As the listbox is in the UI thread, I am not able to access it from the input thread.

So how can I show messages on listbox from the input thread?

public void input()
{
    myTimer.Interval = Int32.Parse(sampleRatetxt.Text);//taking input in  milliseconds
    myTimer.Elapsed += TimerEventProcessor;
    myTimer.Start();
}

private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
    byte[] ba = new byte[52];
    int num = 0;
    {
        NetworkStream stm = tcpclient.GetStream();
        if (stm.DataAvailable)
        {
            num = stm.Read(ba);
            loglistbox.Items.Add("bytes read: " + num);    //cant access listbox                                                      
            string datastring = Convert.ToHexString(ba);
            loglistbox.Items.Add("recived string: " + datastring);     //cant access listbox                                           
            DataPacket packetNew = new DataPacket(datastring);
            loglstbx.Items.Add("recived single packet: " + packetNew.dataPacket);                               //cant access listbox
            loglstbx.Items.Add("frame Length=" + packetNew.frameLength + " | frame ID=" + packetNew.frameID);   //cant access listbox
            loglstbx.Items.Add("val1: " + packetNew.val[0] + "   val2: " + packetNew.val[1]);                    //cant access listbox
            loglstbx.Items.Add("val3: " + packetNew.val[2] + "  val4: " + packetNew.val[3]);                     //cant access listbox
                                                                                                                 //passes the data recieved only if frame Id matches
            if (packetNew.frameID == Int32.Parse(serverIDtxt.Text)) ;
            rawSeries1 = packetNew.val;
            stm.Flush();
        }
    }

Upvotes: 1

Views: 62

Answers (1)

IV.
IV.

Reputation: 9511

In general, the answer to "how to display data from another thread" is to use BeginInvoke to marshal the data back onto the UI thread before setting any properties on any UI control. This minimal reproducible example leaves out the TcpClient code in order to focus on the question at hand.

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        input();
    }
    System.Timers.Timer myTimer = new System.Timers.Timer();
    public void input()
    {
        myTimer.Interval = 500; // Value for test
        myTimer.Elapsed += TimerEventProcessor;
        myTimer.Start();
    }

    private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
    {
        loglistbox.BeginInvoke((MethodInvoker)delegate
        {
            loglistbox.Items.Add("received single packet: ");
            loglistbox.Items.Add($"frame Length = {_rando.Next(10, 21)}");
        });
    }
    // Test data
    Random _rando = new Random(1);
}

screenshot

Upvotes: 2

Related Questions