Ich stehe vor einem komplexen Fehler mit dem Dundas Charting for Winforms-Tool, das mit MS Visual Studio 2008 C# verwendet wird.
Der folgende Fehler tritt auf, wenn ein GUI-Ereignis für das Chart-Objekt ausgelöst wird, während es ungültig gemacht wird. Wenn der Fehler auftritt, zeigt das Dundas-Diagramm ein großes X an. ...
************** 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)
Das Szenario sieht folgendermaßen aus:
- Ich habe eine Gitteransicht, die eine Liste von Objekten enthält, die auf die darzustellende Serie verweisen.
- Die Darstellung wird alle 1 Sekunde mit chart.Invoke(AddData) aktualisiert.
Dies ist das Ereignis, das den Absturz verursacht:
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;
}
}
}
}
Die Zeichnung wird auf folgende Weise angefertigt
Ein Hintergrund-Thread erfasst
Sie hebt das Ereignis
OnDataAvailable jede Sekunde
Hier ist der 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);
}
}
Das Interessante an diesem Fehler ist, dass er nicht auf allen Rechnern auftritt. Mir ist aufgefallen, dass er auf Hochleistungsrechnern wie unserem DELL-Rechner mit 8-Kern-CPU und einem neuen Quad-Core-Laptop auftritt, den wir hier gekauft haben. Dies ließ den Verdacht aufkommen, dass es sich um ein Threading-Problem handelt; allerdings scheint das Threading in Ordnung zu sein, da auf das Diagrammobjekt von demselben Haupt-Thread aus zugegriffen wird.
Bitte helfen Sie mir dabei
UPDATE die Zuordnung über den Setter, der in der Funktion dataGridView1_CellEndEdit stattfindet MUChart.Series[boundData.SeriesName].ChartArea = boundData.ChartArea.ToString(); ruft chart.invalidate intern auf, während die aufgerufene Funktion "AddData", die das Diagramm aktualisiert, diese Funktion explizit aufruft. Ich habe in der MSDN-Bibliothek gelesen, dass "control.invalidate" keine synchrone Zeichnung erzwingt, wenn control.update nicht danach aufgerufen wird. Ich bin mir fast sicher, dass der Konflikt bei der Invalidierung auftritt, obwohl alles auf demselben Thread abläuft, da das Neuzeichnen asynchron erfolgt. Ich habe verstanden, was auf diese Weise geschieht, aber ich weiß nicht, wie ich es vermeiden kann. control.update tut mir nicht gut.
ChangeTheChartConfigurations(); DrawTheChanges() ---- >>>> dies funktioniert asynchron UpdateDataPoints() DrawTheChanges() ---- >>> dies funktioniert, während die erste Änderung noch nicht stattgefunden hat. Zum Beispiel könnte die Serie in einen anderen Diagrammbereich verschoben worden sein und Dundas.Charting.WinControl.AxisScale.a(Double ) (die letzte Funktion im Stacktrace) wird auf einem bereits ausgeblendeten Diagrammbereich aufgerufen das ist nur ein Gedanke
UPDATE
Ich habe die Thread-ID sowohl vom Event-Handler als auch von der AddNewPoint-Funktion protokolliert, und sie war dieselbe wie die des Hauptthreads
0 Stimmen
Bitte bereinigen Sie die Formatierung des Codes. In seinem jetzigen Zustand ist er SEHR schwer zu lesen.
0 Stimmen
Ich habe es bearbeitet, besser geht es nicht
0 Stimmen
Nein, ist es nicht. Entfernen Sie Leerzeilen und entfernen Sie die Einrückung.
0 Stimmen
Ok Ich habe die Bearbeitung abgeschlossen. Hoffentlich bringt mir das Glück
0 Stimmen
Es scheint, dass das Ändern des Status der Chat-Steuerung zu einem ungültigen Status führt, vielleicht sollten Sie etwas tun, bevor Sie den Status ändern. Ich schlage vor, Reflector zu verwenden, um zu sehen, was genau die Ursache für die ausgelöste Ausnahme ist
3 Stimmen
Da Sie Dundas verwenden, denke ich, dass Sie ein einjähriges Abonnement für den Support haben. Schreiben Sie also Ihr Problem in eine Beispiellösung und senden Sie diese an Dundas. Normalerweise sind sie sehr clever und wissen, wie man ihre Tools richtig einsetzt.
0 Stimmen
Ich habe eine Beispiellösung erstellt, konnte den Fehler aber leider nicht reproduzieren. Ich möchte nur, dass sie mir einige Vorschläge machen, warum ein solcher Fehler auftreten könnte.
0 Stimmen
Ich habe ihnen die Anfrage bereits geschickt und warte seit 2 Tagen auf eine Antwort.
0 Stimmen
Sie wissen, dass InvokeRequired immer true sein sollte. Überprüfen Sie, ob dies der Fall ist.
5 Stimmen
Wenn Sie ein Beispiel erstellt haben und in diesem den Fehler nicht reproduzieren können, fangen Sie an, Ihr Beispiel zu vergrößern, bis es ein 1:1 von Ihrer aktuellen Lösung ist. Irgendwann auf dem Weg dorthin sollten Sie das Problem und damit die Ursache finden.
0 Stimmen
In Ihrem ersten UPDATE sagen Sie, dass Sie MUChart.Invalidate() in AddData() aufrufen, aber Ihr Code zeigt, dass Sie dies in AddNewPoint() tun. Haben Sie versucht, es zu verschieben? Siehe die Antwort von fupsduck.