Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Waveform Graph "X" Error

I get an occasional error with waveform graphs, where a graph will "X" out. Instead of displaying the wave form it displays a red "X" from corner to corner.
I'm using the Measurement Studio for .NET. VS 2003, .NET 1.1.
I've attached a bmp of that should show what I'm refering to as well as I've appended the JIT stack dump.
I don't understand what the stack dump is showing as the error.

I am not sure what is causing this behaviour, or what I might be able to do to fix it.

Thanks for any help,
~Sinisa
--------------------------------------
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.HashtableEnumerator.MoveNext()
at Y.b(ComponentDrawArgsInternal )
at Y.DrawForeground(ComponentDrawArgsInternal args)
at NationalInstruments.Restricted.ControlElement.a(ComponentDrawArgsInternal , Rectangle )
at NationalInstruments.Restricted.ControlElement.DrawChildren(ComponentDrawArgsInternal args, Rectangle clipRectangle)
at NationalInstruments.Restricted.ControlElement.a(ComponentDrawArgsInternal , Rectangle )
at NationalInstruments.Restricted.ControlElement.DrawChildren(ComponentDrawArgsInternal args, Rectangle clipRectangle)
at NationalInstruments.Restricted.ControlElement.a(ComponentDrawArgsInternal , Rectangle )
at NationalInstruments.Restricted.ControlElement.Paint(PaintEventArgs e)
at NationalInstruments.UI.WindowsForms.ControlBase.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

.
.
.
0 Kudos
Message 1 of 8
(5,235 Views)
didn't attach last time. will try again
~sinisa
0 Kudos
Message 2 of 8
(5,225 Views)
What member on the graph are you calling when this problem occurs? When and from where are you calling this member (i.e., a control event handler, a timer event handler, hardware API event or callback, etc.)?

From the description and the stack trace, I think the problem is that you're updating the control from a non-UI thread (or more specifically, a thread that's not the thread that the control was created in). The reason that this is a problem is that Windows Forms controls are not thread-safe. Notice that the class overviews of all .NET Framework and Measurement Studio Windows Forms controls have a thread safety section that states:

"Only the following members are safe for multithreaded operations: BeginInvoke, EndInvoke, Invoke, InvokeRequired, and CreateGraphics."

For more information, see the .NET Quickstart article "Making procedure calls across thread boundaries." Please check if this is the problem and post a reply with what you find. Thanks.

- Elton
0 Kudos
Message 3 of 8
(5,218 Views)
Elton,
I'm calling the:
WaveFormPlot.PlotYAppend(double[] yData, System.TimeSpan Increment)
XAxis.Range = new Range(...)

What I am doing in short is:

I send a data array to a class that has a WaveFormGraph in it. The method that accepts the array preprocesses the data and calls the PlotYAppend method. The application does involve too much multithreading. There is a UI thread and a worker thread.
I wonder. If I'm calling this method from the wrong thread (possibly UI thread now that I think obout it) could this explain the behaviour?

I have never been able to duplicate this problem. I have only seen it happen when I was not in the debugger.

Anyways, thanks for the insight. I'll investigate that path, but any further assistance would be greatly appriciated. I hope I've enlightend you of my situation a little bit better.

Thanks,
~sinisa
0 Kudos
Message 4 of 8
(5,216 Views)
"If I'm calling this method from the wrong thread (possibly UI thread now that I think obout it) could this explain the behaviour?"

That would definitely explain the behavior. Try updating the UI via Control.Invoke as described in the article that I mentioned in the previous post.

"I have never been able to duplicate this problem. I have only seen it happen when I was not in the debugger."

That's common when making UI updates across threads; the problems are intermittent. It may appear to work at times, but other times you may get deadlock, exceptions, or partially executed UI updates.

- Elton
0 Kudos
Message 5 of 8
(5,210 Views)
Elton,
I have looked at the doc that you pointed me to. I am not 100% certain that I understood what it was that I was doing wrong based upon this document.

Let me give you a breif overview.

On Load --
do some pre processing
new a method invoker // mi = new MethodInvoker(Go)
start the method invoker // mi.BeginInvoke(null, null)

Go --
while (Keep goining is true)
Collect date from DB
put into arrays
send 2dArray to PlotGraphs function
sleep interval length
end while

PlotGraphs --
for each graph
Call Graph.Chart


Graph.Chart --
preprocess the data
waveformplot.PlotYAppend(data, increment)
-------------------------------------------


It seems to me that all the work is being done from the thread that the methodinvoker started.

Where as the doc had the "background" thread executing the functions.

Are these two things different, and if so how?


Furthermore, I've tried to implement my app another way
now I do this:

on load --
this.thread = new Thread(new ThreadStart(ThreadProc));
this.thread.IsBackground = true;
this.thread.Start();

ThreadProc --
mi = new MethodInvoker(Go);
mi.BeginInvoke(null, null);
// note that the doc had -- this.BeginInvoke(mi) (what's the difference?) -- and that since the while loop is in
// the go function I didn't need it here.

the remaining functions haven't changed.

----------------------

so far it seems to be working (as did the last model).

I appricate any help you can offer.
Thanks,
~Sinisa
0 Kudos
Message 6 of 8
(5,202 Views)
I think I see the confusion. Distinguish between calling BeginInvoke on a delegate and BeginInvoke on a control. BeginInvoke on a delegate invokes a delegate asynchronously on a thread pool thread. BeginInvoke on a control is also asynchronous, but it marshals the call to the thread that the control was created on.

If you perform UI updates via BeginInvoke on a delegate, you will eventually run into the red "X" error again. This is because the UI updates are occurring on a thread pool thread, which will not be the thread that the control was created on. Your updated example is still using BeginInvoke on a delegate, so it has not fixed the problem.

You mentioned that the document had "this.BeginInvoke(mi)" and you asked what the difference is. The difference is that this is the control's BeginInvoke, not a delegate's BeginInvoke, and it marshals the call back to the UI thread so that the UI updates are performed in a thread-safe manner. You need to use BeginInvoke on a control (or a form, which is a control) to resolve the problem.

- Elton
0 Kudos
Message 7 of 8
(5,196 Views)
Elton,
Thanks.
This makes a whole lot more sense now. I've made the suggested changes, and it seems to be behaiving better than before.

~sinisa
0 Kudos
Message 8 of 8
(5,190 Views)