红色X GUI崩溃!我几乎放弃了解决它!

时间:2010-01-05 06:22:37

标签: c# winforms user-interface crash

我正面临着与MS Visual Studio 2008 C#一起使用的Dundas Charting for Winforms工具的复杂错误。

在Chart对象失效时,如果在GUI对象上引发GUI事件,则会发生以下错误。当错误发生时,dundas图表显示一个很大的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)

方案如下:

  • 我有一个网格视图,其中包含引用正在绘制的系列的对象列表。
  • 使用chart.Invoke(AddData)
  • 每1秒更新一次

这是导致崩溃的事件:

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;

            }
        }
    }
}

绘图以下列方式完成

后台线程正在捕获

正在举起活动

OnDataAvailable每秒

这是处理程序

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

这个bug的有趣之处在于它不会在所有机器上发生。我注意到它发生在高规格的机器上,比如我们的8核CPU DELL机器,以及我们在这里购买的新四核笔记本电脑。这引起了线程问题的嫌疑人;但是,线程似乎没问题,因为图表对象是从同一主线程访问的。

请帮我解决这个问题

更新 使用函数dataGridView1_CellEndEdit中发生的setter赋值 MUChart.Series [boundData.SeriesName] .ChartArea = boundData.ChartArea.ToString();在内部调用chart.invalidate, 而更新该图表的调用函数“AddData”会显式调用它。我在MSDN库中读到“control.invalidate”不强制同步绘制,除非在它之后调用control.update。我几乎可以肯定,即使一切都发生在同一个线程上,由于重绘正在异步进行,冲突也会在失效时发生。 我理解这种情况正在发生,但我不知道如何避免它。 control.update对我没有好处。

ChangeTheChartConfigurations(); DrawTheChanges()----&gt;&gt;&gt;&gt;这是异步工作 UpdateDataPoints() DrawTheChanges()----&gt;&gt;&gt;这是有效的,而第一次改变还没有发生。例如,系列可能已被移动到差异图表区域,Dundas.Charting.WinControl.AxisScale.a(Double)(堆栈跟踪中的最后一个函数)正在已隐藏的图表区域上调用。 这只是一个想法

更新

我从事件处理程序和AddNewPoint函数中记录了线程ID,它与主线程的

相同

6 个答案:

答案 0 :(得分:2)

我认为你不应该打电话

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

直接。您应该将其包装到InvokeRequired / Invoke代码中。

同样如此
MUChart.ChartAreas[boundData.ChartArea].Visible = true;

答案 1 :(得分:2)

绘制每个点后,不是使图表无效,而是绘制所有点,然后使图表无效一次。尝试将AddNewPoint()中的MUChart.Invalidate()移动到AddData()中的for循环之后。

答案 2 :(得分:1)

您可能有跨线程操作。

尝试在添加所有点并在主GUI线程中放置MUChart.Invalidate。

当您从另一个线程访问UI控件而不是UI线程时,红色十字通常由.NET框架本身绘制。

当资源不可用或显示控件时发生异常时,也会显示交叉。

答案 3 :(得分:1)

我怀疑你有一个被处置的物体。 (这是你得到的一种奇怪的例外。)一个迹象表明它发生在高端机器上。意思是,机器进行了垃圾收集。

1)当您调用Refresh而不是Invalidate时会发生什么?

2)删除长链对象引用并创建变量。您了解每个{}创建一个本地范围(堆栈)。在图表更新时,这可能会导致对象的范围发生变化。做Series s = MUChart.Series[boundData.SeriesName]; ChartArea a = s.ChartArea; 等等。

3)尝试在AddNewPoint或AddData中锁定或同步对象。您可能正在做的事情也不是控件的线程安全。检查文档。

4)我不会在AddNewPoint中放置try:catch。更好的方法是将它放在for循环之外,但在你的情况下将它放在循环中。

5)你真的不应该使用刷新,更新和无效的调用。这表明您的实现需要减少CPU周期。 (例如,删除try:catch,使用同步锁定解决任何多个“Data Available”事件,删除AddNewPoint方法。)

答案 4 :(得分:0)

请关注以下错误:

  

间隔不能为零参数   name:diff

我认为图表x轴的两个值具有相同的值,因此会引发异常。

答案 5 :(得分:0)

我遇到了同样的错误,发现原因是我将AxisIntervalMode设置为VaiableCount,即使没有数据也是如此。所以我根据系列是否有数据动态更改AxisIntervalMode。希望这可以帮助别人。