09-11-2014 03:01 AM
Hallo,
adding many Scatterplots in multiple Threads in a Scattergraph causes following Exception:
Best regards
Gerald
09-15-2014 03:29 AM
Hi Huschdegutsl,
there is a known bug that is related to Microsoft and this error.
I found a KB from Microsoft about this error and a thread at stackoverflow.com
http://support.microsoft.com/kb/815634/en-us
I hope these links will help to solve your problems.
Regards
swirl
09-15-2014 05:22 AM
Hi swirl,
thank you for your answer. I think it is not my fault, it is a problem in the National.UI.dll.
The Exception is throwing in this dll and i don't have a chance to catch it.
I have attached a small prgramm to generate this exception.
Best regards
Gerald
09-16-2014 03:45 PM
Hi, Gerald
Which version of Visual Studio, .NET, and Measurement Studio are you using? I just ran your example in Visual Studio 2012 using Measurement Studio 2013, and I did not see the error.
Thanks,
09-17-2014 12:17 AM
Hello,
I'm using VS2012 and Measurementstudio 2013. I have debugged and I think there is a problem in this function in the InnerAxisElement class:
private void a(ComponentDrawArgsInternal A_0, RectangleF[] A_1) { PointF tf; PointF tf2; IDictionaryEnumerator enumerator = this.Container.ValueTable.MajorDivisionsHashTable.GetEnumerator(); AxisDrawingInfo info = null; ScaleElement.DivisionBase division = null; if (this.Container.AxisMajorDivisions.LabelBackColor != this.BackColor) { while (enumerator.MoveNext()) { info = (AxisDrawingInfo) enumerator.Value; division = info.Division; this.CalculateTickStartEndCoordinates(division.TickVisible, (float) info.TickStart, division.TickLength, A_0.Bounds, out tf, out tf2); this.a(A_0, info, tf, tf2); if (division.LabelVisible) { PointF location = this.CalculateLabelTopLeftCoordinate(info, tf2); RectangleF labelBounds = new RectangleF(location, info.LabelSize); if (!ScaleElement.LabelOverlapWithCustom(labelBounds, A_1)) { this.a(A_0, info, labelBounds); } } } } else { while (enumerator.MoveNext()) { info = (AxisDrawingInfo) enumerator.Value; division = info.Division; this.CalculateTickStartEndCoordinates(division.TickVisible, (float) info.TickStart, division.TickLength, A_0.Bounds, out tf, out tf2); this.a(A_0, info, tf, tf2); if (division.LabelVisible) { PointF tf4 = this.CalculateLabelTopLeftCoordinate(info, tf2); RectangleF ef2 = new RectangleF(tf4, info.LabelSize); if (!ScaleElement.LabelOverlapWithCustom(ef2, A_1)) { this.b(A_0, info, ef2); } } } } }
There is a movenext over the axisticks, and I change the range of the axis in an other thread, so the enumerator is changed, the Exception is throwed and is catched in the ControlElement and the scope will be disposed in the finally block.
Best regards
Gerald
07-01-2015 04:12 PM - edited 07-01-2015 04:13 PM
Hi, Gerald
Most of the members of the ScatterGraph class are not threadsafe. You can see this in the Thread Safety section at the bottom of the ScatterGraph Class help topic: http://zone.ni.com/reference/en-XX/help/372636F-01/mstudiowebhelp/html/9b6343ca/ . For convenience, I have pasted that section as follows:
Only the following members are safe for multithreaded operations: BeginInvoke, EndInvoke, Invoke, InvokeRequired, andCreateGraphics.
I would recommend posting commands to the thread which constructs your Form
using BeginInvoke
or Invoke
from your threading functions. The code you provided, modified to use BeginInvoke
looks like this, where I have made my changes in bold:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private delegate void plotDelegate(); private void threading() { double count = 0; try { while (true) { this.BeginInvoke((plotDelegate)(() => { this.scatterPlot1.PlotXYAppend(count, count); count++; })); System.Threading.Thread.Sleep(50); } } catch (Exception) { } } int i = 0; private void threading2() { while (true) { this.BeginInvoke((plotDelegate)(() => { this.yAxis1.Range = new NationalInstruments.UI.Range(i, i + 20); i += 10; }));
System.Threading.Thread.Sleep(20); } } private void button1_Click(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(threading)); t.IsBackground = true; t.Start(); System.Threading.Thread.Sleep(2000); Thread t2 = new Thread(new ThreadStart(threading2)); t2.IsBackground = true; t2.Start(); } }