8

I have a long-running process. I want to prevent resource leaks or rogue database connections.

At intervals during the process I want to do this:

  1. get an ArcSDE (Oracle) workspace factory
  2. open a workspace from the factory (at which point I get an open database connection)
  3. get an existing feature class or table on the workspace,
  4. query the feature class or table, loop over the cursor doing my business
  5. then release/close everything such that:

    • The database connection and table lock from ArcSDE/Oracle's perspective (as revealed by something like "sdemon -o info -I users" or a query of the sde.table_locks table) is closed/released.
    • the process is resilient to ArcSDE/Oracle restarts (that is, I'm not leaving something hanging that won't work later after the nightly restart)
    • Any RCW, COM references, and memory are released.

Basically, due to the long-running nature of the process, I want to be really sure I haven't got resource leaks or rogue connections, and my process can survive ArcSDE/Oracle restarts.

I've seen discussions such as:

And this, from which I quote

Each workspace factory maintains a pool of currently connected, active workspaces that are referenced by the application. When any of the previously listed Open* methods are called, the workspace factory verifies if a workspace has previously been opened with a matching set of properties. If so, a reference to the existing instance is returned.

All of which suggests to me that I should release (e.g. ComReleaser class or equivalent Marshal.ReleaseComObject() loop), probably in this order:

  • cursor
  • featureclass/table
  • workspace
  • workspace factory

Then there are discussions like this where people do all that, and maybe even sprinkle in System.GC.Collect() and their database connection still lives.

Oh gurus, what is the final straight dope on this?

  • 1
    Have you tried anything yourself, or are you just asking for advice? The safest bet seems to spawn a new thread or process to do you periodic work. Otherwise in my opinion it would work if you manage to track down all objects and release them according to your plan. If you have a mapcontrol it might also contain references through the layers. – Stefan Oct 16 '14 at 7:42
  • I'm in-progress and asking for advice. Here's a followup question to your comment - If I do the periodic task on a worker thread, should the worker release the workspace factory, or it being a singleton, will that cause probs for other possible simultaneous threads? My guess is I should leave the factory alone? – MC5 Oct 16 '14 at 14:54
  • There are a lot written about the arc objects threading model. Read edndoc.esri.com/arcobjects/9.2/net/… (9.2 but it is still valid I think). It says the singeltons are singeltons per thread, not per process. Also note that threads should be STA and that you can't pass arc objects references between threads. So if you terminate the worker thread it should clean up the factories. Also look in your own link to ESRI-forum where threading is recommended by ESRI as a solution to freeing up connections. – Stefan Oct 17 '14 at 7:01
4

You have already covered many aspects in your post. However to expand on your question, always follow this pattern:

if (obj!=null)
ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(obj);

obj = null;

Then call System.GC.Collect() to force the garbage collector to remove any references to the DBMS.

The order of release have to be Cursors, Features (IFeature), FeatureClasses, Workspaces and other ArcObjects instantiated.

ArcGIS Desktop and ArcEngine application are STA (single threaded application). It is neither safe nor advised to use ArcObjects across threads (Workers); One can use serialization and deserialization of objects to achieve this. For further details, take a look at here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.