7


I am getting some weird errors while trying to implement multithreading with ArcObjects. I am trying following things on per thread basis:

1) Open SDE Workspace
2) Open Feature class
3) Perform Icursor

Eventually, It fails with some errors like: "Memory could not be read or write" or "AccessViolationException".
Looks like there are some memory leaks (though I don't know exactly where).

For more details please refer to the code below:

foreach (string featureClassName in settings.FeatureClassNames)  
{  
            Thread thread = new Thread(new ParameterizedThreadStart(ReadFeatureClass));  
            thread.ApartmentState = ApartmentState.STA;  
            object[] parameters = CreateParameters(featureClassName);  
            thread.Start(parameters);  
}  
    private void ReadFeatureClass(object parameters)  
    {  
        Settings settings;  
        string featureClassName;  
        ExtractParameters(parameters as object[], out settings, out featureClassName); 
        IFeatureWorkspace featureWorkspace = OpenFeatureWorkspace(settings); 
        ITable featureClass = featureWorkspace.OpenTable(featureClassName);  
        Marshal.ReleaseComObject(featureClass);  
        Marshal.ReleaseComObject(featureWorkspace);          
      }    

    private IFeatureWorkspace OpenFeatureWorkspace(Settings settings)  
    {  
        IWorkspaceFactory workspaceFactory = new SdeWorkspaceFactory();  
        IPropertySet connectionProperties = new PropertySet();  
        connectionProperties.SetProperty("SERVER", settings.Server);  
        connectionProperties.SetProperty("INSTANCE", settings.Instance);  
        connectionProperties.SetProperty("USER", settings.User);  
        connectionProperties.SetProperty("PASSWORD", settings.Password);  
        connectionProperties.SetProperty("VERSION", settings.Version);  

        IFeatureWorkspace featureWorkspace = workspaceFactory.Open(connectionProperties, 0) as IFeatureWorkspace;  
        return featureWorkspace;  
    }  
scw
  • 16,391
  • 6
  • 64
  • 101
adhiman
  • 309
  • 2
  • 8
  • On which line does it fail? – Petr Krebs Oct 01 '10 at 09:41
  • Have you read this in the documentation: http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Writing_multithreaded_ArcObjects_code/000100000100000000/ – MathiasWestin Oct 01 '10 at 12:46
  • Mathias: you can tell from the code he is following all the usual COM threading guidelines (at least from my point of view) – Petr Krebs Oct 02 '10 at 03:10
  • ok, maybe I'd replace "new SdeWorkspaceFactory" with an Activator.CreateInstance call (it's a singleton-per-thread), but I do not suspect this to be the problem. i've run your (modified) code with no issues really.. (tested against an in-house SDE instance) – Petr Krebs Oct 02 '10 at 03:15
  • I get random errors in code. Most often it gives AccessViolation exception at this line ITable featureClass = featureWorkspace.OpenTable(featureClassName); You said you ran my code successfully without any issue with your Database. Is there an issue with my DB then.? Any Suggestions? – adhiman Oct 04 '10 at 06:17
  • Any suggestions? – adhiman Oct 14 '10 at 12:05
  • Your code looks OK, but I am curious, what do you expect to do with the rows after you fetched them? – Ragi Yaser Burhum Mar 10 '11 at 01:09
  • I'm with Ragi with asking what the goal is, it doesn't seem like you'd really need to thread that part of the operation out to a background worker – Luke Mar 22 '11 at 16:28
  • Did this ever get resolved? I am facing serious performance issues with AO multi-threading...any ideas? – ujjwalesri Jun 16 '11 at 11:38

1 Answers1

1

As I look at it, without the benefit of what you're looking for with the ICursor, I don't know that you need to fire this off into a new thread. I've used SDE Connections like yours many times. Below is an example from my code base that is currently working (I have an issue when I attempt to CREATE a feature class against a FGDB, but my sde is connecting great)

    public IWorkspace OpenSDEWorkspace(String server, String instance, String database,
        String version, String user, String password)
    {
        try
        {
            //create and populate the property set.
            IPropertySet2 propertySet = new PropertySetClass();
            propertySet.SetProperty("SERVER", server);
            propertySet.SetProperty("INSTANCE", instance);
            propertySet.SetProperty("DATABASE", database);
            propertySet.SetProperty("USER", user);
            propertySet.SetProperty("PASSWORD", password);
            propertySet.SetProperty("VERSION", version);
            IWorkspaceFactory2 sdeWorkspaceFactory;
            sdeWorkspaceFactory = (IWorkspaceFactory2)new SdeWorkspaceFactoryClass();
            IWorkspace workspace = (IWorkspace)sdeWorkspaceFactory.Open(propertySet, 0);

            return workspace;
        }
        catch (Exception e)
        {
            throw new Exception(String.Format("arcSDEWorkspaceOpen: {0}", e.Message), e);
        }
    }

    public ArrayList GetDomainValues(String codedvaluedomain)
    {
        ArrayList arrayList = new ArrayList();
        IWorkspace ws = (IWorkspace)ArcMap.Editor.EditWorkspace;
        if(ws == null)
        {
            ws = OpenSDEWorkspace("ip", "5151", "database", "version", "user", "password");
        }
        IWorkspaceDomains domains = (IWorkspaceDomains)ws;
        object[] domainobject = null;


            IEnumDomain domainEnum = domains.Domains;
            IDomain domain = domainEnum.Next();
            String name = "";

            while (domain != null)
            {
                name = domain.Name;
                domain = domainEnum.Next();
                if (name.Equals(codedvaluedomain))
                { 
                    break;
                }
            }
            ICodedValueDomain codeddomain = new CodedValueDomainClass();
            codeddomain = domains.get_DomainByName(name) as ICodedValueDomain;
            domainobject = new object[codeddomain.CodeCount];

            for (int a = 0; a < codeddomain.CodeCount; a++)
            {
                object domainvalue = codeddomain.get_Value(a);
                String domainvaluename = codeddomain.get_Name(a);
               arrayList.Add(domainvaluename);

            }

        return arrayList;
    }

give your code a run without the thread and let it all run on the main and let me know what happens.

Good luck

Luke

Luke
  • 331
  • 4
  • 11