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;
}
-
On which line does it fail?Petr Krebs– Petr Krebs2010年10月01日 09:41:32 +00:00Commented Oct 1, 2010 at 9:41
-
Have you read this in the documentation: help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/…MathiasWestin– MathiasWestin2010年10月01日 12:46:40 +00:00Commented Oct 1, 2010 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– Petr Krebs2010年10月02日 03:10:50 +00:00Commented Oct 2, 2010 at 3:10
-
ok, maybe I'd replace "new SdeWorkspaceFactory" with an Activator.CreateInstance<T> 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– Petr Krebs2010年10月02日 03:15:12 +00:00Commented Oct 2, 2010 at 3: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– adhiman2010年10月04日 06:17:20 +00:00Commented Oct 4, 2010 at 6:17
1 Answer 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