Red Error X GUI! I almost refused his decision!

I encountered a complex error with the Dundas Charting for Winforms tool used with MS Visual Studio 2008 C #.

The following error occurs when a GUI event is raised on a Chart object when it is invalid. When an error occurs, the dundas chart shows a large X. ...

************** Exception Text ************** System.ArgumentOutOfRangeException: Axis Object - The Interval can not be zero Parameter name: diff at Dundas.Charting.WinControl.AxisScale.a(Double ) at Dundas.Charting.WinControl.Axis.a(Double , Double , AxisScaleSegment , DateTimeIntervalType& ) at Dundas.Charting.WinControl.Axis.a(ChartGraphics , Boolean , AxisScaleSegment , Boolean ) at Dundas.Charting.WinControl.Axis.b(ChartGraphics , Boolean , Boolean ) at Dundas.Charting.WinControl.Axis.Resize(ChartGraphics chartGraph, ElementPosition chartAreaPosition, RectangleF plotArea, Single axesNumber, Boolean autoPlotPosition) at Dundas.Charting.WinControl.ChartArea.a(ChartGraphics ) at Dundas.Charting.WinControl.ChartPicture.Resize(ChartGraphics chartGraph, Boolean calcAreaPositionOnly) at Dundas.Charting.WinControl.ChartPicture.Paint(Graphics graph, Boolean paintTopLevelElementOnly, RenderingType renderingType, XmlTextWriter svgTextWriter, Stream flashStream, String documentTitle, Boolean resizable, Boolean preserveAspectRatio) at Dundas.Charting.WinControl.ChartPicture.Paint(Graphics graph, Boolean paintTopLevelElementOnly) at Dundas.Charting.WinControl.Chart.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.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

The scenario is as follows:

  • I have a grid that has a list of objects that reference a constructed row.
  • The plot is updated every 1 second using a chart. Invoke (AddData)

This is the event that causes the failure:

 private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex >= 0 && e.RowIndex >= 0) { AppDataSeries boundData = dataGridView1[e.ColumnIndex, e.RowIndex].OwningRow.DataBoundItem as AppDataSeries; if (boundData.Tag != null) // Tag is of Type Dundas.Charting.WinControl.Series { switch (e.ColumnIndex) { case 1: MUChart.Series[boundData.SeriesName].ChartArea = boundData.ChartArea.ToString(); // when you change the chart area of a series it // crashes the chart control // also when you enable or disable a series using // series1.Enabled = true, // it could crash the chart control MUChart.ChartAreas[boundData.ChartArea].Visible = true; break; } } } } 

The figure is as follows

Background thread captures

Raises an event

OnDataAvailable every second

Holds the handler

 void serviceWrapperInstance_DataAvailable(object sender, DataAvailableEventArgs e) { if (e.ViewId == currentViewId) { if (MUChart.InvokeRequired) { MUChart.Invoke((MethodInvoker)AddData); } else { AddData(); } } } public void AddData() { if (MUChart.Series.Count > 0) { for (int i = 0; i < currentViewSeries.Count; i++) { AddNewPoint(currentViewSeries[i].XValue, MUChart.Series[i], currentViewSeries[i].YValue * ((currentViewSeries[i].IsInverse) ? -1 : 1), currentViewSeries[i].ChartColor); dataSaver[MUChart.Series[i].Name].Add(new DataPoint(currentViewSeries[i].XValue, (double)currentViewSeries[i].YValue)); } } } public void AddNewPoint(double xValue, Series ptSeries, double yValue, Color pointColor) { try { ptSeries.Points.AddXY(xValue, yValue); if (draggedDroppedSeriesMapper.ContainsKey(ptSeries)) foreach (Series item in draggedDroppedSeriesMapper[ptSeries].DraggedDroppedSeriesVersions) item.Points.AddXY(xValue, yValue); MUChart.Invalidate(); // if I remove the previous line the plot doesn't crash, but doesn't update !! } catch (Exception ex) { Logger.Log(TraceLevel.Error, "AddNewPoint()", ex); } } 

The interesting thing about this error is that it does not happen on all machines. I noticed that this is happening on high-end machines, such as the 8-core DELL processor, and the new quad-core laptop that we got here. This raised a suspicion of a thread problem; however, the threads seem to be in order, since the chart object is accessing from the same main thread.

Please help me with this.

UPDATE is a setter assignment that takes place in the dataGridView1_CellEndEdit function MUChart.Series [boundData.SeriesName] .ChartArea = boundData.ChartArea.ToString (); calls chart.invalidate internally, while the called AddData function, which updates this chart, calls it explicitly. I read in the MSDN library that "control.invalidate" does not cause synchronous paint if control.update is called after it. I am pretty sure that the conflict occurs in the event of invalidity, although everything happens in the same thread, since the redrawing occurs asynchronously. I realized that this is happening, but I do not know how to avoid it. control.update does nothing good to me.

ChangeTheChartConfigurations (); DrawTheChanges () ---- โ†’ โ†’ it works asynchronously UpdateDataPoints () DrawTheChanges () ---- โ†’> it works while the first change has not yet occurred. For example, a series could be moved to the area of โ€‹โ€‹difference diagrams, and Dundas.Charting.WinControl.AxisScale.a (Double) (the last function in the stack trace) is called in the already hidden region of the diagram. that just a thought

UPDATE

I registered the thread ID from both the event handler and the AddNewPoint function, and it was the same as

main stream
+6
user-interface c # winforms crash
source share
6 answers

Instead of nullifying the graph after drawing each point, draw all the dots and then invalidate the graph. Try moving MUChart.Invalidate () from AddNewPoint () after the for loop to AddData ().

+2
source share

I think you shouldn't call

 MUChart.Series[boundData.SeriesName].ChartArea = boundData.ChartArea.ToString(); 

directly. You have to port it to the InvokeRequired / Invoke code. And the same for

 MUChart.ChartAreas[boundData.ChartArea].Visible = true; 
+2
source share

You probably have a crossflow operation.

Try placing your MUChart.Invalidate after all the points have been added and in the main GUI thread.

The red cross is usually drawn by the .NET platform itself when accessing the user interface control from a thread other than the user interface thread.

An intersection is also displayed when a resource is unavailable or an exception appears in the control.

+1
source share

I suspect you have an object that has been deleted. (This is an odd exception that you get.) An indicator is your claim that this happens on high-performance machines. Meaning, the machine has collected garbage.

1) What happens when you call Refresh instead of Invalidate?

2) Remove the long chain of references to objects and create variables. You understand that each {} creates a local area (stack). This can lead to a change in the scope of the object while updating the chart. Make Series s = MUChart.Series[boundData.SeriesName]; ChartArea a = s.ChartArea; Series s = MUChart.Series[boundData.SeriesName]; ChartArea a = s.ChartArea; etc.

3) Try to lock or synchronize the object in AddNewPoint or AddData. It is also possible that what you are doing is not thread safe for the control. Check the documentation.

4) I would not put try: catch in AddNewPoint. Itโ€™s better to place it outside the for loop, but in your case put it in a loop.

5) You really should not use calls to update, update, and invalidate. This indicates that your implementation requires fewer processor cycles. (For example, removing try: catch, accessing any available data multiple events, using synchronization lock, removing the AddNewPoint method.)

+1
source share

Please focus on the following error:

The interval cannot be zero Parameter name: diff

I think that the two values โ€‹โ€‹for the x-axis of the chart have the same value, so an exception occurs.

0
source share

I met the same error and found that I set AxisIntervalMode as VaiableCount, even if there is no data. Therefore, I dynamically change AxisIntervalMode according to whether the series has data. Hope this can help someone.

0
source share

All Articles