0

Why does this code get a memory overflow error for datasets with more than 20k of data?

int nMax = (int)numFIDTo.Value;
            int nMin = (int)numFIDFrom.Value;
            IStepProgressor stepProg = ArcMap.Application.StatusBar.ProgressBar;
            stepProg.MinRange = 0;
            stepProg.MaxRange = nMax;
            stepProg.Position = 0;
            stepProg.Show();
            try
            {
                IMap map = ArcMap.Document.ActiveView.FocusMap;
                IFeatureLayer flCrater = ClsShare.GetLayerFromName(map, comboBox1.Text) as IFeatureLayer;
                bool isPolygon = check_isPokygon.Checked;
                FrmAddField frmAddField = new FrmAddField(flCrater);
                int field_R = frmAddField.AddField("local_R", esriFieldType.esriFieldTypeDouble, true);
                IFeatureClass fcCrater = flCrater.FeatureClass;
                if (fcCrater == null)
                {
                    MessageBox.Show("撞击坑图层要素为空!");
                }
                IGeoDataset geodataset = fcCrater as IGeoDataset;
                ISpatialReference spatialR_Crater = geodataset.SpatialReference;
                IGeographicCoordinateSystem geoSys = ClsShare.GetGeographicCoordinateSystem(spatialR_Crater);
                IFeatureCursor featureCursor = fcCrater.Update(null, false);
                IFeature feature = null;
                double dDiam = 0;
                double dR = 0;
                IClone polyClone;
                IPolyline polylineClone;
                while ((feature = featureCursor.NextFeature()) != null)
                {
                    if (feature.OID < nMin || feature.OID > nMax)
                        continue;
                    if (feature.ShapeCopy.IsEmpty) continue;
                  
                    IPolygon polygonSrc = feature.ShapeCopy as IPolygon;
                    IPolyline polylineSrc = new PolylineClass();
                    polylineSrc.SpatialReference = polygonSrc.SpatialReference;
                    ISegmentCollection segs = polylineSrc as ISegmentCollection;
                    segs.AddSegmentCollection(polygonSrc as ISegmentCollection);
                    IPoint ptCenter = ClsShare.GetCenter(polygonSrc as IGeometry);
                    // 将中心点首先投影到地里坐标系上
                    ptCenter.Project(geoSys);
                    // 创建局部投影坐标系
                    IProjectedCoordinateSystem prjLocal = ClsShare.CreateLocalProjectedCoordinateSystem(
                    geoSys, 0, 0, 1.0, 0, ptCenter.X, ptCenter.Y);

                    polyClone  = polylineSrc as IClone;
                    polylineClone = polyClone.Clone() as IPolyline;
                    polylineClone.Project(prjLocal);
                    if (polylineClone.IsEmpty) continue;

                    IGeometry geoPoly = polylineClone as IGeometry;

                    //!<得到圆的外包最长边作为圆直径
                    dDiam = 0.0;
                    if (isPolygon)
                    {
                        //!<如果是提取任意多边形的最长直径,则要取矩形框的对角线长度作为最长值
                        dDiam = Math.Sqrt(geoPoly.Envelope.Width * geoPoly.Envelope.Width + geoPoly.Envelope.Height * geoPoly.Envelope.Height);
                    }
                    else
                    {
                        dDiam = Math.Max(geoPoly.Envelope.Width, geoPoly.Envelope.Height);
                    }

                    dR = dDiam / 2.0;
                    feature.set_Value(field_R,dR);
                    featureCursor.UpdateFeature(feature);
                    stepProg.Step();

                    System.Runtime.InteropServices.Marshal.ReleaseComObject(feature);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(polygonSrc);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(polylineSrc);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(ptCenter);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(prjLocal);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(segs);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(geoPoly);
                }
                stepProg.Hide();
                MessageBox.Show("撞击坑更新完成");
                System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
                System.GC.Collect();
                System.GC.WaitForPendingFinalizers();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message+"");
            }

I updated my code, but it still reports outofmemory error, which makes me more confused.

            IMap map = ArcMap.Document.ActiveView.FocusMap;
            IFeatureLayer flCrater = ClsShare.GetLayerFromName(map, comboBox1.Text) as IFeatureLayer;
            bool isPolygon = check_isPokygon.Checked;
            FrmAddField frmAddField = new FrmAddField(flCrater);
            int field_R = frmAddField.AddField("local_R", esriFieldType.esriFieldTypeDouble, true);
            IFeatureClass fcCrater = flCrater.FeatureClass;
            IGeoDataset geodataset = fcCrater as IGeoDataset;
            ISpatialReference spatialR_Crater = geodataset.SpatialReference;
            IGeographicCoordinateSystem geoSys = ClsShare.GetGeographicCoordinateSystem(spatialR_Crater);

            IFeatureCursor featureCursor = fcCrater.Update(null, true);
            IFeature feature = null;
            double dDiam = 0;
            double dR = 0;
            
            
            IPolyline polylineSrc = new PolylineClass();
            ISegmentCollection segs = polylineSrc as ISegmentCollection;
            
            while ((feature = featureCursor.NextFeature()) != null)
            {
                if (feature.OID < nMin || feature.OID > nMax)
                    continue;
                if (feature.Shape.IsEmpty) continue;
                // 将圆变成圆弧进行投影
                dDiam = GetDiameterFromFea(feature, geoSys, isPolygon);
                if (dDiam < 0) continue;

                dR = dDiam / 2.0;
                feature.set_Value(field_R,dR);
                featureCursor.UpdateFeature(feature);
                stepProg.Step();
            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);

'''

1
  • Try declaring your objects before the loop; I've had similar issues - from what I understand (and I might be wrong, but it seems to fix the issue for me) you're creating new objects faster than the system memory manager can keep up with, you've only got 4GiB MAX addressable RAM to work with. If you're re-using your objects then they stick in-place. Lines like if (feature.ShapeCopy.IsEmpty) continue; throws a new instantiated object into your memory space and that makes it cluttered, unable to find empty space to make a new object on the fly, here I'd use if (feature.Shape.IsEmpty) instead. Commented Feb 29 at 7:47

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.