Reputation: 11
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
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);
}
Upvotes: 2