ฝ่ายสนับสนุนของ ESRI กล่าวว่าพวกเขาทำซ้ำปัญหาและได้เปิดรายงานข้อผิดพลาด (NIM070156)
ผมตั้งใจว่าจะมีการรั่วไหลของหน่วยความจำ (ในความทรงจำที่ไม่มีการจัดการกอง) ที่เกิดขึ้นเมื่อเครื่องมือในของฉัน .NET / C # ArcMap เพิ่มในการดำเนินการสอบถามเชิงพื้นที่ (ส่งคืนICursor
จากIFeatureClass.Search
ที่มีISpatialFilter
ตัวกรองแบบสอบถาม) วัตถุ COM ทั้งหมดจะได้รับการปล่อยตัวโดยเร็วที่สุดเท่าที่พวกเขาจะไม่จำเป็น (ใช้Marshal.FinalReleaseCOMObject
)
เมื่อต้องการตรวจสอบสิ่งนี้ฉันจะตั้งค่าเซสชัน PerfMon ด้วยตัวนับสำหรับ Private Bytes, Virtual Bytes และ Working Set ของ ArcMap.exe และตั้งข้อสังเกตว่าทั้งสามเพิ่มขึ้นอย่างต่อเนื่อง (โดยประมาณ 500KB ต่อการทำซ้ำ) ด้วยการใช้เครื่องมือแต่ละครั้ง . สิ่งสำคัญนี้จะเกิดขึ้นเฉพาะเมื่อดำเนินการกับคลาสคุณลักษณะบน SDE โดยใช้การเชื่อมต่อโดยตรง (หน่วยเก็บข้อมูล ST_Geometry, ไคลเอ็นต์ Oracle 11g และเซิร์ฟเวอร์) ตัวนับยังคงคงที่เมื่อใช้ Geodatabase ของไฟล์เช่นเดียวกับเมื่อเชื่อมต่อกับอินสแตนซ์ SDE รุ่นเก่าที่ใช้การเชื่อมต่อแอปพลิเคชัน
จากนั้นฉันก็ใช้LeakDiagและLDGrapher (พร้อมคำแนะนำจากบล็อกโพสต์นี้) และบันทึกโปรแกรม Windows Heap Allocator สามครั้ง: เมื่อฉันโหลด ArcMap ครั้งแรกและเลือกเครื่องมือเพื่อเริ่มต้นมันหลังจากใช้เครื่องมือสองสามครั้งและหลังจากทำงาน อีกไม่กี่ครั้ง
นี่คือผลลัพธ์ที่แสดงในมุมมองเริ่มต้นของ LDGrapher (ขนาดโดยรวม):
นี่คือ call stack สำหรับสายสีแดง:
ในขณะที่คุณสามารถดูSgsShapeFindRelation2
ฟังก์ชั่นใน sg.dll ดูเหมือนจะเป็นสิ่งที่รับผิดชอบต่อหน่วยความจำรั่ว
ที่ฉันเข้าใจ sg.dll เป็นห้องสมุดรูปทรงเรขาคณิตหลักที่ใช้โดย ArcObjects และSgsShapeFindRelation2
น่าจะเป็นที่ที่ตัวกรองเชิงพื้นที่จะถูกนำไปใช้
ก่อนที่ฉันจะทำสิ่งใดฉันต้องการดูว่ามีใครประสบปัญหานี้หรือไม่ นอกจากนี้สิ่งที่อาจเป็นสาเหตุของสิ่งนี้เกิดขึ้นเฉพาะกับการเชื่อมต่อโดยตรง? เสียงนี้ดูเหมือนข้อบกพร่องใน ArcObjects ปัญหาการกำหนดค่าหรือปัญหาการเขียนโปรแกรมหรือไม่?
นี่เป็นวิธีการทำงานรุ่นที่เล็กที่สุดที่ทำให้เกิดพฤติกรรมนี้
private string GetValueAtPoint(IPoint pPoint, IFeatureClass pFeatureClass, string pFieldName)
{
string results = "";
ISpatialFilter pSpatialFilter = null;
ICursor pCursor = null;
IRow pRow = null;
try
{
pSpatialFilter = new SpatialFilterClass();
pSpatialFilter.Geometry = pPoint;
pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
pSpatialFilter.SearchOrder = esriSearchOrder.esriSearchOrderSpatial;
pCursor = (ICursor)pFeatureClass.Search(pSpatialFilter, false);
pRow = pCursor.NextRow();
if (pRow != null)
results = pRow.get_Value(pFeatureClass.FindField(pFieldName)).ToString();
}
finally
{
// Explicitly release COM objects
if (pRow != null)
Marshal.FinalReleaseComObject(pRow);
if (pCursor != null)
Marshal.FinalReleaseComObject(pCursor);
if (pSpatialFilter != null)
Marshal.FinalReleaseComObject(pSpatialFilter);
}
return results;
}
นี่คือรหัสการแก้ปัญหาของฉันตามการสนทนาด้านล่างกับ Ragi:
private bool PointIntersectsFeature(IPoint pPoint, IFeature pFeature)
{
bool returnVal = false;
ITopologicalOperator pTopoOp = null;
IGeometry pGeom = null;
try
{
pTopoOp = ((IClone)pPoint).Clone() as ITopologicalOperator;
if (pTopoOp != null)
{
pGeom = pTopoOp.Intersect(pFeature.Shape, esriGeometryDimension.esriGeometry0Dimension);
if (pGeom != null && !(pGeom.IsEmpty))
returnVal = true;
}
}
finally
{
// Explicitly release COM objects
if (pGeom != null)
Marshal.FinalReleaseComObject(pGeom);
if (pTopoOp != null)
Marshal.FinalReleaseComObject(pTopoOp);
}
return returnVal;
}
private string GetValueAtPoint(IPoint pPoint, IFeatureClass pFeatureClass, string pFieldName)
{
string results = "";
ISpatialFilter pSpatialFilter = null;
IFeatureCursor pFeatureCursor = null;
IFeature pFeature = null;
try
{
pSpatialFilter = new SpatialFilterClass();
pSpatialFilter.Geometry = pPoint;
pSpatialFilter.GeometryField = pFeatureClass.ShapeFieldName;
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelEnvelopeIntersects;
pFeatureCursor = pFeatureClass.Search(pSpatialFilter, true);
pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
if (PointIntersectsFeature(pPoint, pFeature))
{
results = pFeature.get_Value(pFeatureClass.FindField(pFieldName)).ToString();
break;
}
pFeature = pFeatureCursor.NextFeature();
}
}
finally
{
// Explicitly release COM objects
if (pFeature != null)
Marshal.FinalReleaseComObject(pFeature);
if (pFeatureCursor != null)
Marshal.FinalReleaseComObject(pFeatureCursor);
if (pSpatialFilter != null)
Marshal.FinalReleaseComObject(pSpatialFilter);
}
return results;
}