Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

InvalidOperationException in Graphplot

Hallo,

 

adding many Scatterplots in multiple Threads in a Scattergraph causes following Exception:

 

NationalException1.PNG

 

NationalException2.PNG

 

Best regards

 

Gerald

0 Kudos
Message 1 of 6
(5,805 Views)

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

http://stackoverflow.com/questions/7761959/collection-was-modified-enumeration-operation-may-not-exe...

 

I hope these links will help to solve your problems.

 

Regards

swirl

0 Kudos
Message 2 of 6
(5,770 Views)

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

 

0 Kudos
Message 3 of 6
(5,761 Views)

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,

Daniel Dorroh
National Instruments
0 Kudos
Message 4 of 6
(5,736 Views)

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

 

 

0 Kudos
Message 5 of 6
(5,731 Views)

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:

 

Thread Safety

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(); } }

 

0 Kudos
Message 6 of 6
(4,806 Views)