[...]
I'm not making the main GUI thread sleep nor am I doing an
Application.DoEvents().
Then it's difficult to understand your question.
In the thread where I handle the data
parsing, I then make a call to the function which adds the data points
to the graph (which happens on the main GUI thread through the
delegate callback), then I do a Thread.Sleep(10) at the end of the
loop to tell that thread to sleep for 10ms.
You should be aware that Thread.Sleep() does not have enough precision for
that to be a reliable way to ensure that a thread actually sleeps for
10ms. Due to the way the Windows thread scheduler works, a thread that
calls Thread.Sleep(10) may not be run again for much longer (depending on
what's going on in the system, 50ms, 100ms, or longer).
I have also added
textboxes on the form which I am now updating from the same thread
through a callback to the main UI thread, and now that I'm doing that
everything seems to be working fine.
As I mentioned, without a concise-but-complete code sample that reliably
demonstrates the problem, it's not possible to comment with any real
reliability. Both because there's no way to know what your code is doing,
and because there's no way to know for sure what the actual symptoms are.
Likewise, it's impossible to say why adding text boxes would make your
problem go away.
As long as we are relying on plain English descriptions of everything, you
are not likely to get very useful answers. It's just not possible.
When I take out the call to the
function which updates the textboxes, everything is slow again (for
instance mousing over a button does not give it the highlighted
outline anywhere near as quick as it should). I'm really not sure
why... Perhaps it's something to do with the graph control that I'm
using (Dundas Charts)? Thanks for your help by the way.
You're welcome. It could very well be some side-effect caused by the
graph control you're using. But again, impossible to say without seeing a
concise-but-complete code sample. A simple graph control could be written
in quick order -- maybe 30 minutes or so -- and you could try replacing
the third-party control with such a test control, to see if that makes the
problem go away.
If it does, then you have a reliable indication that you should be taking
this up with the author's of that third-party control. If it doesn't,
then you have taken one solid step toward having a suitable
concise-but-complete code sample that you can post here for others to look
at.
Pete
This is obviously a trimmed down version of the whole thing, but
should show you what I'm doing. ProcessUsbData is the thread which
reads in the data and calls the functions to update the graph and
textboxes. If I take out the UpdateO2Textbox(O2) and UpdateCO2Textbox
(CO2) calls then the symptoms I'm seeing crop up. By the way, please
feel free to let me know if any of my code sucks and could be done in
a more efficient manner. For instance, if I'm supposed to be reading
from a USB once every 10 seconds is there a better way to do it than
doing Thread.Sleep(10) and then checking the inbound buffer? Thanks
again!
public partial class frmSampleForm : Form
{
private bool bAbortRead;
Thread BufferReader;
delegate void AddDataPointCallback(string series, decimal x,
decimal y);
delegate void UpdateO2TextboxCallback(decimal pValue);
delegate void UpdateCO2TextboxCallback(decimal pValue);
public frmTesting_VerifySetup(ref cExercise_Test pTest)
{
InitializeComponent();
ReadUSB();
}
private void ReadUSB()
{
// Start the thread which reads the inbound buffer
bAbortRead = false;
BufferReader = new Thread(new ThreadStart(ProcessUsbData));
BufferReader.Start();
}
private void ProcessUsbData()
{
string[] data;
decimal O2;
decimal CO2;
TimeSpan ts;
DateTime startTime = DateTime.Now;
while(!bAbortRead)
{
data = device.ReadLine().Split(new char[]{','});
if(data.Length > O2INDEX)
decimal.TryParse(data[O2INDEX], out O2);
else
O2 = 0;
if(data.Length > CO2INDEX)
decimal.TryParse(data[CO2INDEX], out CO2);
else
CO2 = 0;
ts = DateTime.Now - startTime;
if(O2 > 0 && O2 < 100)
{
AddDataPoint("O2", (decimal)(ts.TotalSeconds),
O2);
UpdateO2Textbox(O2);
}
if(CO2 > 0 && CO2 < 100)
{
AddDataPoint("CO2", (decimal)(ts.TotalSeconds),
CO2);
UpdateCO2Textbox(CO2);
}
Thread.Sleep(10);
}
}
private void AddDataPoint(string series, decimal x, decimal y)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if(chart1.InvokeRequired)
{
AddDataPointCallback d = new AddDataPointCallback
(AddDataPoint);
Invoke(d, new object[] { series, x, y });
}
else
{
chart1.Series[series].Points.AddXY(x, y);
chart1.Invalidate();
}
}
private void UpdateO2Textbox(decimal pValue)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if(txtO2.InvokeRequired)
{
UpdateO2TextboxCallback d = new UpdateO2TextboxCallback
(UpdateO2Textbox);
Invoke(d, new object[] { pValue });
}
else
{
txtO2.Text = pValue.ToString("0.00");
}
}
private void UpdateCO2Textbox(decimal pValue)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if(txtCO2.InvokeRequired)
{
UpdateCO2TextboxCallback d = new
UpdateCO2TextboxCallback(UpdateCO2Textbox);
Invoke(d, new object[] { pValue });
}
else
{
txtCO2.Text = pValue.ToString("0.00");
}
}
}