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

mus*_*bar 6 c# crash user-interface winforms

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

当Chart对象在其无效时引发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)
Run Code Online (Sandbox Code Playgroud)

方案如下:

  • 我有一个网格视图,其中包含引用正在绘制的系列的对象列表.
  • 该图使用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;

            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

绘图以下列方式完成

后台线程正在捕获

它正在提升这一事件

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

请在这件事上给予我帮助

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

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

UPDATE

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

fup*_*uck 2

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