I'm a noob in C# and ArcObjects (started two weeks ago).
I'm trying to write a stand-alone console program that will change label placement quality in all data frames for all MXD files in a given folder. What I've got now kind of works, but after 40 or 50 MXDs that are changed, my program throws "out of memory exception". I suppose that standard garbage collection fails in this case. When I watch memory usage in task manager for this process, it fluctuates (so some memory is freed from time to time) but with a steady tendency upwards.
I have searched Google and SDK help as well for this topic. In general they say that all the COM objects created by oneself should be explicitly destroyed, as well as cursors and enumerators.
See the code below. The only time I use new
explicitly is when creating MapDocument object and I immediately add it to ComReleaser - so, the way I understand it, it should be taken care of at the end of using
block. I don't have any enumerators nor cursors, as I deal with layout only. What else should I release?
foreach (System.IO.FileInfo file in files)
{
counter++;
if (!log.Exists(file.FullName))
{
using (ComReleaser cr = new ComReleaser())
{
bool changed = false;
Console.WriteLine("({0}/{1}) Opening: " + file.FullName, counter, total);
//Open mxd
MapDocument mapDoc = new MapDocument();
cr.ManageLifetime(mapDoc);
mapDoc.Open(file.FullName);
//Iterate data frames
for (int i = 0; i < mapDoc.MapCount; i++)
{
Map map = (Map)mapDoc.Map[i];
Console.WriteLine("Dataframe {0}", map.Name);
IAnnotateMap2 annoMap = (IAnnotateMap2)map.AnnotationEngine;
IMapOverposter overposter = (IMapOverposter)map;
//check if Maplex labeling engine
if (overposter.OverposterProperties is IMaplexOverposterProperties)
{
IMaplexOverposterProperties overposterProps = (IMaplexOverposterProperties)overposter.OverposterProperties;
Console.WriteLine("Current placement quality: {0}", overposterProps.PlacementQuality.ToString());
//change placement quality if necessary
if (overposterProps.PlacementQuality != quality)
{
Console.WriteLine("Changing...");
overposterProps.PlacementQuality = quality;
changed = true;
}
else
{
Console.WriteLine("No need to change.");
}
Console.WriteLine("Current placement quality: {0}", overposterProps.PlacementQuality.ToString());
}
else
{
Console.WriteLine("Dataframe does not use Maplex.");
}
}
//Save document if needed
if (changed)
{
mapDoc.Save();
Console.WriteLine("Saving...");
}
//close mxd
Console.WriteLine("Closing...");
mapDoc.Close();
log.Add(file.FullName);
}//ComReleaser
} else
{
Console.WriteLine("({0}/{1}) Skipping: " + file.FullName, counter, total);
}
}