ESRI.ArcGIS.Geoprocessor.Geoprocessor unable to release memory

1455
5
11-26-2018 02:10 AM
umasuryasykam1
New Contributor II

Below script is very standard for running any geoprocessing tool using ArcObjects but it hardly releases memory. It is helping the tool crashes after processing few 100 datasets. Please help in this regard. Thanks in advance.

geoprocessor.ClearMessages();
// Set the overwrite output option to true
geoprocessor.OverwriteOutput = true;
try
{
Logger.Write("RunTool is started", "AppLog");


// Execute the tool
geoprocessor.Execute(process, null);
ReturnMessages(geoprocessor);


ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(geoprocessor);
ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(process);
geoprocessor = null;
process = null;

}
catch (Exception ex)
{
Logger.Write("Exception in RunTool::"+ex.Message, "ExceptionHandling");
ReturnMessages(geoprocessor);
}

0 Kudos
5 Replies
DuncanHornby
MVP Notable Contributor

You seemed to have neglected to say what exactly it is you are running? What is process in geoprocessor.Execute(process, null)? What Tool is it and what where the supplied parameters?

0 Kudos
umasuryasykam1
New Contributor II

Hi,

I missed it accidentally just  due to considered it as abstraction as it happened for all types of operations in general such as 'Project', 'Merge' etc. Few others we moved to use plain arcobjects using c# related to geodatabase.

The other parameters would be shapefile paths depending on the parameters require for a given operation.

0 Kudos
MilanasSkačkauskas1
New Contributor

@umasurya sykam First of all - your code missing "finally" block. You need to realease all COM objects int it. So if exception occurs in some situations - it always release COM objects and it's memory. For example:

Geoprocessor geoprocessor = null;

Process  process= null;

try

{

geoprocessor = new Geoprocessor();

process =  new Process();

geoprocessor.Execute(process, null);
ReturnMessages(geoprocessor);

}

catch() 

{

Logger.Write("Exception in RunTool::"+ex.Message, "ExceptionHandling");
ReturnMessages(geoprocessor);

}

finaly

{

if(geoprocessor != null)

{

ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(geoprocessor);

geoprocessor =null;

}

if(process != null)

{

ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(process );

process =null;

}

}

0 Kudos
umasuryasykam1
New Contributor II

Hi,

Although I'm not releasing within finally block, they are being released within the try block itself properly and those 2 lines of code always get executed. But memory is not being recovered after that.

Another question I have is normally we are releasing eari COM objects using Marshal.ReleaseComObject.

Is the Geoprocessor class not a COM object?

0 Kudos
MilanasSkačkauskas1
New Contributor

You need to check if it is COM object, if not - check if it is IDisposable. I have smart function for that:

public static int Release(object comObj)
{
   try
   { 
      if (comObj != null)
      {
         if (Marshal.IsComObject(comObj))
         {
            try
            {
               return Marshal.ReleaseComObject(comObj);
            }
            catch
            {
               comObj = null;
            }
         }
         else
         {
            var disposable = comObj as IDisposable;
            if (disposable != null)
            {
               disposable.Dispose();
               return 0;
            }
         }
      }

   }
   catch (Exception ex)
   {

      System.Diagnostics.Debug.WriteLine("CATCH: " + ex.Message);
   }
   return -999;
}

How to use function: 

finally
{
   if (geoprocessor != null)
   {
      Release(geoprocessor);
      geoprocessor= null;
   }

}