Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have a method that does a bunch of geoprocessing on some layers for my ArcMap extension. It creates a feature-to-point layer for one FeatureClass and another feature-to-point layer for another FeatureClass. Then one of the feature-to-point layer's is used to as input to create a Buffer layer. This all works without any errors until I try to run the method in a separate thread. When I run it in a separate thread, both feature-to-point tools run without errors but it fails when it tries to create the buffer.

I borrowed error handling for my geoprocessing from Issues with geoprocessing with .NET. The result shows the following.

Executing: Buffer GPL0 C:\Users\me\Documents\geoprocess.gdb\buffer "250 Feet" FULL ROUND NONE # esriGPMessageTypeProcessDefinition
Start Time: Tue Mar 06 18:55:10 2012 esriGPMessageTypeProcessStart
Failed to execute. Parameters are not valid. esriGPMessageTypeError
ERROR 000732: Input Features: Dataset GPL0 does not exist or is not supported

It seems when I try to run this in a separate thread, the name of the input FeatureClass to the buffer tool gets lost and changed to "GPL0" which doesn't exist. I've read that there can be issues when passing objects between threads but all the geoprocessing is happening in the same thread (as far as I understand). I pass an IMap variable and some other objects to the method. The IMap object seems to be passed okay since I can get its layers and the other objects are not used for the geoprocessing.

In my form:

backgroundWorker.DoWork += (obj, eArgs) => BgWorkerDoWork(map, ...)
bgwCalibrate.RunWorkerAsync();

private void BgWorkerDoWork(IMap map, ...)
{
  var thread = new Thread(() => MyClass.MyGeoProcessMethod(map, ...));
  thread.SetApartmentState(ApartmentState.STA);
  thread.Start();
  thread.Join();
}

In my class MyClass:

private void MyGeoProcessMethod(IMap map, ...)
{
  // do stuff...
  // then create both feature-to-point files
  IFeatureClass inFeatureClass1 = map.Layer[0] as IFeatureClass;
  IFeatureClass inFeatureClass2 = map.Layer[1] as IFeatureClass;
  // no errors:
  IFeatureClass polygonsToPoints1 = CreateFeatureToPoint(inFeatureClass1);
  IFeatureClass polygonsToPoints2 = CreateFeatureToPoint(inFeatureClass2);
  // Create buffer (this is the part that fails)    
  IFeatureClass bufferFeatureClass = CreateBuffer(polygonsToPoints2);
}

Both feature-to-point layers get created successfully. The geoprocessing events say so and I can see the results on the map. Any suggestions or ideas on what's going on with the buffer part?

share|improve this question
add comment

2 Answers

In which thread have you initilised the Geoprocessor?

The ESRI Geoprocessor is not thread safe, and it's usages across threads often gives rise to cryptic errors. Your error might be due to this reason.

share|improve this answer
    
A new geoprocessor object gets initialized for each tool (Buffer, Feature to point) in the second thread I created. –  thelastlombax Mar 8 '12 at 3:41
add comment

There are several other threads about multithreading with ArcObjects (like this one) as well as ArcObjects documentation for it.

Right of the bat, I can tell you that you are passing the map to the thread and are accessing the layer objects from the other thread. This can lead to nasty errors in ArcObjects; at best cross COM apartment marshaling, at worst, super weird errors and crashes).

Pass only a string, create a brand new connections, to the workspace and re-open them along with the FeatureClass. Otherwise you are asking for trouble.

share|improve this answer
    
I didn't think passing the map was an issue since I was able to create both feature-to-point layers successfully but I guess the buffer not working is an example of a super weird error like you said. I will try passing strings strings and update with results. –  thelastlombax Mar 8 '12 at 4:00
    
@thelastlombax Workspaces have apartment thread affinity. In fact, 99% of ArcObjects that are implemented as singletons achieve this by having an internal hash that uses the threadid. –  Ragi Yaser Burhum Mar 8 '12 at 16:04
    
Then it sounds like everything will have to be created again in the separate thread instead of passing as a string. I don't see a way to pass the IMap variable as a string. I looked into IXMLSerialize interface but there doesn't seem to be any useful coclasses that implement IXMLSerialize. I'll just recreate the workspace and the objects. –  thelastlombax Mar 9 '12 at 6:36
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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