ThinkGeo.com    |     Documentation    |     Premium Support

The FeatureSource is not open. Please call the Open method before calling this method

 Guys, what would cause this exception even though I am calling Layer.Open before Layer.QueryTools?


This is the stack trace:


 



Type : System.InvalidOperationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089


Message : The FeatureSource is not open.   Please call the Open method before calling this method.


Source : MapSuiteCore


Help link : 


Data : System.Collections.ListDictionaryInternal


TargetSite : System.Collections.ObjectModel.Collection`1[ThinkGeo.MapSuite.Core.Feature] GetFeaturesInsideBoundingBoxCore(ThinkGeo.MapSuite.Core.RectangleShape, System.Collections.Generic.IEnumerable`1[System.String])


Stack Trace :    at ThinkGeo.MapSuite.Core.InMemoryFeatureSource.GetFeaturesInsideBoundingBoxCore(RectangleShape boundingBox, IEnumerable`1 returningColumnNames)


   at ThinkGeo.MapSuite.Core.FeatureSource.GetFeaturesNearestToCore(BaseShape targetShape, GeographyUnit unitOfData, Int32 numberOfItemsToFind, IEnumerable`1 returningColumnNames)


   at ThinkGeo.MapSuite.Core.FeatureSource.GetFeaturesNearestTo(BaseShape targetShape, GeographyUnit unitOfFeatureSource, Int32 numberOfItemsToFind, IEnumerable`1 returningColumnNames)


   at ThinkGeo.MapSuite.Core.QueryTools.GetFeaturesNearestTo(BaseShape targetShape, GeographyUnit unitOfData, Int32 numberOfItemsToFind, IEnumerable`1 returningColumnNames)


   at EMS.ThinkGeoLibrary.MapSuite.Utilities.FeatureFinderHelper.QueryFeatures(BaseShape shape, FeatureLayer layer, IEnumerable`1 columnnNames, GeographyUnit gUnit, DistanceUnit dUnit, SpatialOperationType ops, Int32 numberOfFeaturesToReturn)


TIA.


 



Klaus, 
  
 I tried to recreate this issue but with no luck. So I guess you are using some special logic such as multi-threading. Could you provide me a simple sample which is very helpful for us to recreate this issue? 
  
 Thanks, 
  
 James 


 James, this is probably related to the other posting.  Yes, there I have a background thread that occassionally update the InternalCollection of my InMemoryFeatureLayer.  While this is going on a query may be happening on the main UI thread.  Do you guys lock collection somehow when somehow is clearing and adding Features to InMemoryFeatureLayer.InternalCollection?



Klaus, 
  
 Yes, I think they’re related, let us discuss this issue at the other posting. We couldn’t lock the collection when you clear or add feature because we don’t know when you edit the collection, I think you can do it at your code, when you call GeoCollection.Clear() or Add() you can add a lock. 
  
 James

James, just need to re-visit this thread to ask a question specific to this issue.


If I call FeatureLayer.Open(), does this internally call FeatureLayer.FeatureSource.Open() or do I have to explicitly do so?  I am still have this error even after doing the following:


 

 lock (layer)
                {
                    if (!layer.IsOpen)
                        layer.Open();




As additional and related question, Is it a bad practice not to call the Layer.Close method at any time? I guess it’s a waste of resources being opening and closing it all the time, as I do updates oftenly. Is all the .Close stuff being executed anyway on object normal dispose?

Klaus,



When you call FeatureLayer.Open(), it internally call FeatureLayer.FeatureSource.Open(). You may need to lock the layer for every thread which uses QueryTools.


Here is the sample code which recreates this issue.



static void Main(string[] args)
{
    InMemoryFeatureLayer layer = new InMemoryFeatureLayer();
    layer.InternalFeatures.Add(new Feature(1, 1, Guid.NewGuid().ToString()));

    for (int j = 0; j < 1000; j++)
    {
        Task task = new Task(() =>
            {
                // If we remove the lock, the error will happen in some thread.
                lock (layer)
                {
                    if (!layer.IsOpen)
                    {
                        layer.Open();
                    }
                    Thread.Sleep(1000);
                    Collection<Feature> features = layer.QueryTools.GetAllFeatures(ReturningColumnsType.NoColumns);
                    layer.Close();
                }
            });
        task.Start();
    }

    Console.Read();
}


-------------


Carlos,


Here are the answers for your questions:


1. Is it a bad practice not to call the Layer.Close method at any time? 


     We recommend you call the Layer.Close method at any time for the following reasons: 


   1) In most layers integrated with MapSuite (InMemoryFeatureLayer, ShapeFileFeatureLayer...), the time cost for .Open/.Close method is extremely small.


   2) It’s better to call .Open before using resources and call .Close after, in this way we don't need to hold the resources when don't need to use them.


   3) If a layer contains some unmanaged resources, it’s better to call .Close method to release these expensive resources which will not released by GC. 


2. Is all the .Close stuff being executed anyway on object normal dispose?


    We don't have any customized logic in object's finalize method, but when a Layer is disposed,  GC will automatically release its managed resources.


    If a layer contains unmanaged resources (through inheritting the existing layer),  the unmanaged resources will not be cleaned up by GC and we should call .Close method (which should include the logic for releasing unmanged resources) to release all the resources.


 

Thanks,


Ivan