Dukungan ESRI mengatakan mereka telah mereproduksi masalah ini dan telah membuka laporan bug (NIM070156).
Saya telah menentukan bahwa ada kebocoran memori (dalam memori tumpukan yang tidak dikelola) yang terjadi ketika alat di .NET / C # ArcMap add-in melakukan kueri spasial (mengembalikan ICursor
dari IFeatureClass.Search
dengan ISpatialFilter
filter kueri). Semua objek COM dilepaskan segera setelah tidak diperlukan lagi (menggunakan Marshal.FinalReleaseCOMObject
).
Untuk menentukan ini, saya pertama kali mengatur sesi PerfMon dengan penghitung untuk ArcMap.exe Private Bytes, Virtual Bytes dan Working Set, dan mencatat bahwa ketiganya terus meningkat (sekitar 500KB per iterasi) dengan setiap penggunaan alat yang melakukan kueri . Yang terpenting, ini hanya terjadi ketika dilakukan terhadap kelas fitur pada SDE menggunakan koneksi langsung (penyimpanan ST_Geometry, klien dan server Oracle 11g). Penghitung tetap konstan saat menggunakan file geodatabase, serta saat menghubungkan ke instance SDE yang lebih lama yang menggunakan aplikasi connect.
Saya kemudian menggunakan LeakDiag dan LDGrapher (dengan beberapa panduan dari posting blog ini ) dan mencatat Windows Heap Allocator sebanyak tiga kali: ketika saya pertama kali memuat ArcMap dan memilih alat untuk menginisialisasi, setelah menjalankan alat beberapa lusin kali, dan setelah menjalankan beberapa lusin kali.
Berikut adalah hasil seperti yang ditunjukkan pada tampilan default LDGrapher (ukuran total):
Inilah tumpukan panggilan untuk saluran merah:
Seperti yang Anda lihat, SgsShapeFindRelation2
fungsi dalam sg.dll tampaknya bertanggung jawab atas kebocoran memori.
Seperti yang saya mengerti, sg.dll adalah pustaka geometri inti yang digunakan oleh ArcObjects, dan SgsShapeFindRelation2
mungkin di mana filter spasial sedang diterapkan.
Sebelum saya melakukan hal lain, saya hanya ingin melihat apakah ada orang lain yang mengalami masalah ini (atau sesuatu yang serupa) dan bagaimana jika ada sesuatu yang dapat mereka lakukan tentang hal itu. Juga apa yang bisa menjadi alasan terjadinya ini hanya dengan koneksi langsung? Apakah ini terdengar seperti bug di ArcObjects, masalah konfigurasi, atau masalah pemrograman?
Berikut ini adalah versi minimal dari metode yang menghasilkan perilaku ini:
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;
}
Ini kode solusi saya berdasarkan diskusi di bawah ini dengan 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;
}