Reputation: 81
I would like some advise on threading as I'm new to it. I've read several articles on threading online.
I'm reading com ports data. I would like to use threading such that it will read the data every 5 seconds and update the data on the listbox. Currently, all the data is being read. I'm unsure where to start.
Where shall i start putting my thread codes? I'm using Windows Form,c# VS2008.
Here's my codes to read the data from com ports:
void datareceived(object sender, SerialDataReceivedEventArgs e)
{
myDelegate d = new myDelegate(update);
listBox1.Invoke(d, new object[] { });
}
public void update()
{
while (serialPortN.BytesToRead > 0)
bBuffer.Add((byte)serialPortN.ReadByte());
ProcessBuffer(bBuffer);
}
private void ProcessBuffer(List<byte> bBuffer)
{
int numberOfBytesToRead = 125;
if (bBuffer.Count >= numberOfBytesToRead)
{
listBox1.Items.Add("SP: " + (bBuffer[43].ToString()) + " " + " HR: " + (bBuffer[103].ToString()));
// Remove the bytes read from the list
bBuffer.RemoveRange(0, numberOfBytesToRead);
}
}
Thanks all!
Upvotes: 0
Views: 4058
Reputation: 13501
Why not use a timer? Put it into the InitializeComponent method of the form that is appropriate,
using System.Timers;
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "Form1";
Timer timer = new Timer();
timer.Interval = 5000;
timer.Elapsed += new ElapsedEventHandler(TimerElapsed);
//timer.Enabled = true; // you may need this, but probably not if you are calling the start method.
timer.Start();
}
void TimerElapsed(object sender, ElapsedEventArgs e)
{
// put your code here to read the COM port
}
The only other problem with this code is that you will get an exception Cross-thread operation not valid.
You will have to modify your code like this,
private void ProcessBuffer(List<byte> bBuffer)
{
int numberOfBytesToRead = 125;
if (bBuffer.Count >= numberOfBytesToRead)
{
this.Invoke(new Action(() =>
{
listBox1.Items.Add("SP: " + (bBuffer[43].ToString()) + " " + " HR: " + (bBuffer[103].ToString()));
});
// Remove the bytes read from the list
bBuffer.RemoveRange(0, numberOfBytesToRead);
}
}
The reason is that the ProcessBuffer method will be running on a background thread. Background threads cannot access UI components on the UI thread. So you have to call this.Invoke which will run that update to the listbox on the UI thread.
Have a look here if you want to know more about the Invoke method,
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
UPDATE:
So within the TimerElapsed method you will want to call your code, but it is not clear to me which part of your code it should call? What is the 'datareceived' method for, there is nothing calling it in your code snippet.
So I am guessing it will be this,
void TimerElapsed(object sender, ElapsedEventArgs e)
{
Update();
}
public void Update()
{
while (serialPortN.BytesToRead > 0)
buffer.Add((byte)serialPortN.ReadByte());
ProcessBuffer(buffer);
}
It doesn't make sense for it to be calling the ProcessBuffer method because where will the buffer come from?
If I am not on the right track perhaps expand your code sample, and I am happy to help more.
Please note a few style changes I made to your code (feel free to take them or leave them), a method in C# should start with a capital letter, and calling the variable bBuffer is not standard in C#. Another point if that method is only called from within the class it should be made private.
Upvotes: 2