加载大量数据时WPF内存不足错误

时间:2012-11-28 15:22:12

标签: c# wpf xaml exception charts

我需要为我的自定义控件将大量数据处理为单个List<ChartData>。 达到列表计数80,00,000后,它可以正常工作大约300万点它会引发内存不足错误。列表是否有任何计数限制?是的意思是我应该使用任何其他集合而不是列表。

是否有更好的技术将大量数据加载到内存中? proplem在以下函数中。如果ChartIndexedDataPoint.Count超过30,00,000

 protected override void CalculateSegments(ChartSeries series, ChartIndexedDataPoint[] points)
    {
        double[] yCoef={0};
        IChartDataPoint startPoint = null;
        IChartDataPoint endPoint = null;
        ChartPoint startControlPoint = null;
        ChartPoint endControlPoint = null;
        if (points.Length >= 2)
        {
            NaturalSpline(points, out yCoef);
            if (series.ShowEmptyPoints == false && series.Area.EnableLazyLoading == true)
            {
                allpoints = new List<IChartDataPoint>();
                if (series.ActualYAxis.IsAutoSetRange == true || series.ActualXAxis.IsAutoSetRange == true)
                {
                    series.Segments.Clear();
                    series.Adornments.Clear();

                    for (int i = 0, count = points.Length; i < count - 1; i++)
                    {
                        startPoint = points[i].DataPoint;
                        endPoint = points[i + 1].DataPoint;
                        GetBezierControlPoints(startPoint, endPoint, yCoef[i], yCoef[i + 1], out startControlPoint, out endControlPoint);
                        allpoints.Add(startPoint);
                        allpoints.Add(startControlPoint);
                        allpoints.Add(endControlPoint);
                        allpoints.Add(endPoint);
                    }
                    series.Segments.Add(new ChartFastSplineSegment(allpoints, points, series)); 
                    return;
                }
                if (series.Segments.Count != 0)
                {
                    ChartFastSplineSegment segment = ((ChartFastSplineSegment)series.Segments[0]);

                    if (segment.Points != null && segment.Points.Count < points.Length)
                    {
                        segment.GetSegmet(points[points.Length - 1].DataPoint, series);
                    }
                    else if (segment.Points == null || segment.Points.Count > points.Length)
                    {                           
                        for (int i = 0, count = points.Length; i < count - 1; i++)
                        {
                            startPoint = points[i].DataPoint;
                            endPoint = points[i + 1].DataPoint;
                            GetBezierControlPoints(startPoint, endPoint, yCoef[i], yCoef[i + 1], out startControlPoint, out endControlPoint);
                            allpoints.Add(startPoint);
                            allpoints.Add(startControlPoint);
                            allpoints.Add(endControlPoint);
                            allpoints.Add(endPoint);
                        }
                        segment.UpdateSegment(allpoints, series);
                        segment.refresh = true;
                    }
                }
                else
                {                        
                    for (int i = 0, count = points.Length; i < count - 1; i++)
                    {
                        startPoint = points[i].DataPoint;
                        endPoint = points[i + 1].DataPoint;
                        GetBezierControlPoints(startPoint, endPoint, yCoef[i], yCoef[i + 1], out startControlPoint, out endControlPoint);
                        allpoints.Add(startPoint);
                        allpoints.Add(startControlPoint);
                        allpoints.Add(endControlPoint);
                        allpoints.Add(endPoint);
                    }
                    series.Segments.Add(new ChartFastSplineSegment(allpoints, points, series)); 
                }
            }
            else if (series.Segments.Count == 0 || series.internaldata_modified || allpoints.Count > points.Length)
            {
                allpoints = new List<IChartDataPoint>();
                series.Segments.Clear();
                series.Adornments.Clear();
                ChartIndexedDataPoint[] pts = points;
                List<ChartIndexedDataPoint> tempPointArray = new List<ChartIndexedDataPoint>();                    
                for (int i = 0; i < pts.Length-1; i++)
                {
                    switch (pts[i].DataPoint.EmptyPoint)
                    {
                        case false:
                            {
                                startPoint = points[i].DataPoint;
                                endPoint = points[i + 1].DataPoint;
                                GetBezierControlPoints(startPoint, endPoint, yCoef[i], yCoef[i + 1], out startControlPoint, out endControlPoint);
                                allpoints.Add(startPoint);
                                allpoints.Add(startControlPoint);
                                allpoints.Add(endControlPoint);
                                allpoints.Add(endPoint);
                                tempPointArray.Add(pts[i]);
                                break;
                            }
                        case true:
                            {
                                if (allpoints.Count > 0)
                                {
                                    if (i < points.Length)
                                    {
                                        startPoint = points[i].DataPoint;
                                        endPoint = points[i + 1].DataPoint;
                                        GetBezierControlPoints(startPoint, endPoint, yCoef[i], yCoef[i + 1], out startControlPoint, out endControlPoint);
                                        allpoints.Add(startPoint);
                                        allpoints.Add(startControlPoint);
                                        allpoints.Add(endControlPoint);
                                        allpoints.Add(endPoint);
                                    }
                                    tempPointArray.Add(points[i]);

                                }
                                break;
                            }
                    }
                }
                if (tempPointArray.Count != 0 && allpoints.Count != 0)
                {
                    series.Segments.Add(new ChartFastSplineSegment(allpoints, tempPointArray.ToArray(), series));
                }
            }
            if (series.Segments.Count > 0)
            {
                List<ChartIndexedDataPoint> tempPointArray = new List<ChartIndexedDataPoint>();
                List<ChartIndexedDataPoint> pts = points.ToList();

                if (!series.Contains_emptypt)
                {
                    int cnt = (allpoints.Count+4)/4;
                    while ((allpoints.Count + 4) / 4 != points.Length && (allpoints.Count + 4) / 4 < points.Length)
                    {
                        startPoint = points[cnt-1].DataPoint;
                        endPoint = points[cnt].DataPoint;
                        GetBezierControlPoints(startPoint, endPoint, yCoef[cnt-1], yCoef[cnt], out startControlPoint, out endControlPoint);
                        allpoints.Add(startPoint);
                        allpoints.Add(startControlPoint);
                        allpoints.Add(endControlPoint);
                        allpoints.Add(endPoint);
                        cnt++;
                    }
                }
                (series.Segments[0] as ChartFastSplineSegment).m_points = allpoints;
                if (series.ActualXAxis.IsAutoSetRange || series.Zoomactionenabled)
                {                        
                    double X_MAX = allpoints.Max(x => x.X);
                    double X_MIN = allpoints.Min(x => x.X);
                    (series.Segments[0] as ChartFastSplineSegment).xRange = new DoubleRange(X_MIN, X_MAX);//xRange + cdpt.X;
                    if (series.ActualXAxis.RangeCalculationMode == RangeCalculationMode.AdjustAcrossChartTypes)
                    {
                        (series.Segments[0] as ChartFastSplineSegment).xRange += (series.Segments[0] as ChartFastSplineSegment).xRange.Start - 0.5;
                        (series.Segments[0] as ChartFastSplineSegment).xRange += (series.Segments[0] as ChartFastSplineSegment).xRange.End + 0.5;
                    }
                    (series.Segments[0] as ChartFastSplineSegment).SetRange(series);

                }
                if (series.ActualYAxis.IsAutoSetRange || series.Zoomactionenabled)
                {                        
                    double Y_MAX = allpoints.Max(y => y.Y);
                    double Y_MIN = allpoints.Min(y => y.Y);

                    (series.Segments[0] as ChartFastSplineSegment).yRange = new DoubleRange(Y_MIN, Y_MAX);//yRange + cdpt.Y;

                    if (series.ActualXAxis.RangeCalculationMode == RangeCalculationMode.AdjustAcrossChartTypes)
                    {
                        (series.Segments[0] as ChartFastSplineSegment).xRange += (series.Segments[0] as ChartFastSplineSegment).xRange.Start - 0.5;
                        (series.Segments[0] as ChartFastSplineSegment).xRange += (series.Segments[0] as ChartFastSplineSegment).xRange.End + 0.5;
                    }

                    (series.Segments[0] as ChartFastSplineSegment).SetRange(series);
                    if (series.Zoomactionenabled)
                    {
                        series.Zoomactionenabled = false;
                    }
                }
            }
        }     
    }

3 个答案:

答案 0 :(得分:2)

您的应用程序可以使用数据虚拟化吗? http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization

答案 1 :(得分:2)

即使没有内存问题,也没有任何有意义的方法可以一次性呈现所有这些信息,而无需以某种方式对其进行总结。您拥有的数据点数多于1920x1080屏幕中的像素数。您需要考虑减少对您的用例有意义的点数的方法。

答案 2 :(得分:0)

最后我解决了这个问题。

allpoints.Add(startPoint);
allpoints.Add(startControlPoint);
allpoints.Add(endControlPoint);
allpoints.Add(endPoint);

allpoints分为4个列表

startPoints<IChartDataPoint>
endControlPointS<IChartDataPoint>
endControlPointS<IChartDataPoint>
endPointS<IChartDataPoint>