ThinkGeo.com    |     Documentation    |     Premium Support

System.InvalidOperationException - The FeatureSource is not open. Please call the Open Method before calling this method

I have been getting a System.InvalidOperationException seemingly randomly while I am running my program.  The additional information says: The FeatureSource is not open.  Please call the Open Method before calling this method.



I am including my code below.  It should be comprehensive enough to give you an idea of what I am doing or at least trying to do.  Basically, I have a point layer displayed on the map, and I am drawing in a polygon layer.  When the polygon layer finishes drawing, it looks for the nearest point and creates a highlight layer for it (inmemoryfeaturelayer).  I am pulling attribute data from the point and joining it to the polygon.  I am letting the user see which point is closest to their polygon shape by using the highlight layer.  The highlight layer copies the point layer’s closest feature, and it creates a larger different color symbol to place over top of the closest feature.  This part is done automatically.  



I am trying to let me user select a different point if they decide they want to use a different feature.  So, I have it set so they click on the visible dialog to change things around.  I remove the normal map_click event that I had been using and add another one to route to my code below.  I have been playing around with this and could not get it to crash the same way twice.  I keep getting that exception; sometimes at 2 clicks on new features, other times at 30.



I saw something on your web application forms about a concurrency issue, but I would not know how to tackle that with WPF.  Especially since I denote open and close methods anytime I am accessing a layer.  I have been trying to trace it down using console messages, but it does not seem consistent when crashing.  The one thing I did notice happens frequently even though I am not refreshing the map is Map Suite Trace: GoogleMapsLayer Request Image Count: * appearing in my console messages.



Any advice would be great.  I am trying to provide you enough information without overwhelming you in my process here.  I left most of it tact so it might have some other functions that either return shapefile names or something else.  Those have been working for the most part.  I am just confused on what is causing the exception since I haven’t been able to track it down.  Thanks in advance!


001.Private Sub ReselectJoinFeature(ByVal sender As ObjectByVal As ThinkGeo.MapSuite.WpfDesktopEdition.MapClickWpfMapEventArgs)
002.        Dim newJoinFeature As Feature
003.        newJoinFeature = New Feature
004.        Dim transferResults() As Object
005. 
006.        'select the new feature, change the highlight layer
007.        newJoinFeature = SetNewJoinFeatureValue(e)
008.         
009.        If newJoinFeature IsNot Nothing Then
010.            'this next function just queries a database looking for fields/layer names that need to move attribute data
011.            'to/from
012.            transferResults = CheckForTransferValues(activeLayer.Name, valueTransferCollection(0).Name, newJoinFeature)
013. 
014.            If transferResults(4) <> “” Then
015.                valueTransferResult = transferResults(4)
016.            Else
017.                valueTransferResult = ""
018.            End If
019.        Else
020.            Console.WriteLine(“reselectjoinfeature is nothing”)
021.        End If
022.    End Sub
023.     
024.     
025.Private Function SetNewJoinFeatureValue(ByVal As ThinkGeo.MapSuite.WpfDesktopEdition.MapClickWpfMapEventArgs) As Feature
026.        'I remove the original map click handler and add in a handler for this one.  At this point, there is
027.        'already a point feature in the highlightoverlay that is shown on screen
028.        'the idea behind this is to click another point on the map to change the selection and also 
029.        'change which feature is 'highlighted’
030.        'I am just overlapping the original feature with the highlightoverlay
031.        Dim featureCollection As Collection(Of Feature)
032.        Dim joiningLayerName As String
033.        Dim tempAttributeLayer() As String
034.        Dim newFeature As Feature
035.        Dim joinLayer As ShapeFileFeatureLayer
036.        Dim shapeType As ShapeFileType
037. 
038.        'these next four lines are just there to grab a name for the target shapefile for the highlight overlay
039.        'they run into some functions that just adjust what name we are referring to from our database
040.        tempAttributeLayer = Split(txtSpJoinLayer.Text, “:”)
041.        joiningLayerName = tempAttributeLayer(1).Trim
042.        joiningLayerName = ReturnInternalNameFromUserName(joiningLayerName)
043.        joinLayer = ReturnShapefileFromLayerName(joiningLayerName)
044. 
045.        joinLayer.Open()
046.        joinLayer.FeatureSource.Open()
047. 
048.        shapeType = joinLayer.GetShapeFileType
049. 
050.        joinLayer.FeatureSource.Close()
051.        joinLayer.Close()
052. 
053.        'this function should return a collection (of 1 feature)
054.        'pass in the mouse click location and the name of the layer we are looking for
055.        featureCollection = SelectFeatures(e, joiningLayerName)
056. 
057.        ''assign the feature to a feature variable
058.        If featureCollection IsNot Nothing Then
059.            If featureCollection.Count > 0 Then
060.                newFeature = New Feature
061.                newFeature = featureCollection.Item(0)
062.                'if we were able to select a feature, it will be passed into the sub to add it to the highlight overlay
063.                CreateHighlightFeature(shapeType, newFeature)
064. 
065.                'select and return something
066.                Return newFeature
067.            End If
068.        End If
069.        Return Nothing
070. 
071.End Function
072. 
073.     
074.Private Function SelectFeatures(ByVal As ThinkGeo.MapSuite.WpfDesktopEdition.MapClickWpfMapEventArgs, Optional ByVal targetLayer As String NothingAs Collection(Of Feature)
075. 
076.        Dim selectedfeatures As Collection(Of Feature)
077.        Dim box As RectangleShape
078.        Dim xAdjust As Double
079.        Dim xOverlay As New LayerOverlay()
080.        Dim xFeature1 As New Feature
081.         
082.            xlayer = ReturnShapefileFromLayerName(targetLayer)
083.             
084.            'we are using a function here to try to ascertain the current zoom level in order to make a size appropriate 
085.            'box to grab a feature
086.            Select Case GetZoomLevel(WpfMap_Main)
087.                Case To 5
088.                    xAdjust = 10000
089.                Case To 7
090.                    xAdjust = 5000
091.                Case 8
092.                    xAdjust = 4000
093.                Case 9
094.                    xAdjust = 3000
095.                Case 10
096.                    xAdjust = 2000
097.                Case 11
098.                    xAdjust = 450
099.                Case 12
100.                    xAdjust = 300
101.                Case 13
102.                    xAdjust = 100
103.                Case 14
104.                    xAdjust = 60
105.                Case 15
106.                    xAdjust = 30
107.                Case 16
108.                    xAdjust = 20
109.                Case 17
110.                    xAdjust = 10
111.                Case 18
112.                    xAdjust = 5
113.                Case 19
114.                    xAdjust = 2
115.                Case 20
116.                    xAdjust = 1
117.            End Select
118.             
119.            'here we create that box
120.            box = New RectangleShape(e.WorldX - xAdjust, e.WorldY + xAdjust, e.WorldX + xAdjust, e.WorldY - xAdjust)
121. 
122.            xlayer.Open()
123.            xlayer.FeatureSource.Open()
124.            If xlayer.GetShapeFileType = ShapeFileType.Point Then
125.                selectedfeatures = xlayer.QueryTools.GetFeaturesWithin(box, ReturningColumnsType.AllColumns)
126.            Else 'xlayer.GetShapeFileType = ShapeFileType.Polygon in this case - need to add functionality for lines, etc depending on what kind of selection method we want
127.                selectedfeatures = xlayer.QueryTools.GetFeaturesIntersecting(box, ReturningColumnsType.AllColumns)
128.            End If
129.            xlayer.FeatureSource.Close()
130.            xlayer.Close()
131. 
132.            If selectedfeatures.Count > 0 Then
133.                Return selectedfeatures
134.            Else
135.                Return Nothing
136.            End If
137. 
138.  
139. 
140.End Function
141. 
142.Private Sub CreateHighlightFeature(ByVal shapeType As ShapeFileType, ByVal newFeature As Feature)
143. 
144.        'since I am running this sub repeatedly and I only want one feature shown in the highlight overlay
145.        'I first check the overlay’s featurelayer (highlightfeaturelayer) for content and clear it
146.        'remove inmemoryfeaturelayer features
147.        highlightFeatureLayer.Open()
148.        highlightFeatureLayer.FeatureSource.Open()
149.         
150.        If highlightFeatureLayer.InternalFeatures.Count > 0 Then
151.            highlightFeatureLayer.InternalFeatures.Clear()
152.        End If
153.         
154.        highlightFeatureLayer.FeatureSource.Close()
155.        highlightFeatureLayer.Close()
156. 
157.        'here I take the shapetype that was passed in from newFeature’s shapefile to determine symbology
158.        Select Case (shapeType)
159.            Case ShapeFileType.Point
160.                highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.GhostWhite, 8, GeoColor.StandardColors.Black)
161.            Case ShapeFileType.Polygon
162.                highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.GhostWhite, GeoColor.StandardColors.Black, 3)
163.            Case ShapeFileType.Polyline
164.                highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.StandardColors.GhostWhite, 3, True)
165. 
166.        End Select
167.         
168.        'the rest of this should be generic enough to have here instead of in the select case
169.        highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
170.        highlightFeatureLayer.Open()
171.        highlightFeatureLayer.FeatureSource.Open()
172.        highlightFeatureLayer.FeatureSource.BeginTransaction()
173.        highlightFeatureLayer.FeatureSource.AddFeature(newFeature)
174.        highlightFeatureLayer.FeatureSource.CommitTransaction()
175.        highlightFeatureLayer.FeatureSource.Close()
176.        highlightFeatureLayer.Close()
177. 
178.        highlightOverlay.Layers.Add(highlightFeatureLayer)
179.         
180.        'the highlightOverlay was added to the map during initialization so I am only adjusting its contents
181.        'with this sub
182.         
183.        WpfMap_Main.Refresh()
184. 
185.        originalTransferValueFeature(2) = shapeType
186. 
187.    End Sub
188.     
189.Private Function ReturnShapefileFromLayerName(ByVal layerName As StringAs ShapeFileFeatureLayer
190.        If layerName <> “” Then
191. 
192. 
193.            Dim overlayCollection As New Collection(Of LayerOverlay)
194.            Dim layerCollection As New Collection(Of ShapeFileFeatureLayer)
195. 
196.            overlayCollection.Clear()
197.            layerCollection.Clear()
198. 
199.            'need to build a collection of work layers and basemap layers
200. 
201.            For As Integer = 0 To WpfMap_Main.Overlays.Count - 1 Step 1
202.                'Console.WriteLine(WpfMap_Main.Overlays.Item(i).ToString)
203.                If WpfMap_Main.Overlays(i).GetType.ToString = “ThinkGeo.MapSuite.WpfDesktopEdition.LayerOverlay” Then
204. 
205.                    overlayCollection.Add(WpfMap_Main.Overlays(i))
206. 
207.                End If
208.            Next
209. 
210.            For As Integer = 0 To overlayCollection.Count - 1 Step 1
211. 
212.                For As Integer = 0 To overlayCollection.Item(i).Layers.Count - 1 Step 1
213. 
214.                    'Console.WriteLine(overlayCollection.Item(i).Layers(j).GetType().ToString)
215.                    overlayCollection.Item(i).Layers(j).Open()
216.                    If overlayCollection.Item(i).Layers(j).GetType.ToString = “ThinkGeo.MapSuite.Core.ShapeFileFeatureLayer” Then
217.                        overlayCollection.Item(i).Layers(j).Close()
218.                        layerCollection.Add(overlayCollection.Item(i).Layers(j))
219.                    End If
220.                Next
221. 
222.            Next
223. 
224.            For As Integer = 0 To layerCollection.Count - 1 Step 1
225.                If layerCollection.Item(i).Name = layerName Then
226.                    Return layerCollection.Item(i)
227. 
228.                End If
229. 
230.            Next
231.            Return Nothing
232. 
233.        Else
234.            Return Nothing
235.        End If
236.End Function


Hi Brandon, 
  
 I haven’t found problem from your code, it looks you have open each layer before use it. 
  
 Sorry I haven’t succeed reproduced this exception from your code, have you noticed which line throw that exception? 
  
 And it looks you don’t have too many layers, I think you can open them but not close until application is closed. 
  
 If you want to find the really problem, you should want to build a really simple sample which can reproduce it and upload that, we will help you debug it. 
  
 Regards, 
  
 Don

I am trying to trim down my project to have you help me out, but I don’t think there is a way to truly simplify down what I am trying to do into a simple project.  My project incorporates a directives database, basemap shapefiles, and work layer shapefiles that are designed especially for this project.



Is there another way I can get my project over to you to look at so you can get the grand scale of what I am trying to accomplish?  Plus, if I can avoid posting the project on a public forum, that would be best since since we are planning on distributing the software.



Thanks!

Hi Brandon, 
  
 You can create a ticket and upload your project there, it’s totally private. Or you can send email to forumsupport@thinkgeo.com and the title should be post id, this post’id is 11927. 
  
 If possible, please streamline your project as possible, and in particular to exclude the relevant part of database, a program which can run independently will make reproduce work easier.  
  
 Regards, 
  
 Don

I sent a follow up to the forumsupport@thinkgeo.com.  However, I had a couple of questions while I am waiting for a response.  I have been trying to track down the issue, and I have been scouring the forums here to come up with answers.  I have a couple of things that I wanted to check about to see if they could be causing my issue. 
  
 It seems like the exceptions happen when I am dealing with an InMemoryFeatureLayer, and they happen after I am editing its contents through .AddFeature() and .Clear().  I was reading another user’s issue where the issue dealt with the spatial index not being updated, and the map being refreshed.  Instead of putting everything into an EditTools collection, I just added .BuildIndex() methods between the InMemoryFeatureLayer update and the map refresh.  So far, that has not worked yet. 
  
 Another thing I saw looked into locking the overlay that I am editing.  It seems like with the WPF version that overlay locking/releasing is done automatically now?  Is that something we still need to consider? 
  
 One last thing I saw to help stop the program from crashing on the exceptions was to adjust the overlay drawing exception mode to DrawingExceptionMode.DrawException so I should see pink tiles instead of crashing. 
  
 I am not sure if any of that is applicable to me.  I get more than just the FeatureSource is not Open exception when doing this process, so I cannot be sure what I may be doing wrong.  If you have any sample code that does the same thing I am trying to do (and doesn’t crash), that would be great.  If not, I will wait to hear back from forum support.


Hi Brondon,

In “AttributeTransfer.vb” ReselectJoinFeature,
Map object is refreshed twice,  the one is “SetNewJoinFeatureValue(e)” and
the other is “CheckForTransferValues”. After “SetNewJoinFeatureValue” has been
invoked, the map begins to draw, but “CheckForTransferValues” is immediately
invoked following “SetNewJoinFeatureValue”. In “CheckForTransferValues”, some
work layers have been closed, but the others are still drawing. The drawing
condition is opening layer, so the not open exception has been thrown.


To fix this issue,  the “WpfMap_Main.Refresh()”
must be commented in “CreateHighlightFeature.vb/CreateHighlightFeature”, and “WpfMap_Main.Refresh()”
will be added into “AttributeTransfer.vb/ReselectJoinFeature” as following
diagram:


CreateHighlightFeature.vb/CreateHighlightFeature:





Private Sub CreateHighlightFeature(ByVal shapeType As ShapeFileType, ByVal newFeature As Feature)
        Console.WriteLine(“inside createhighlightfeature…beginning”)
 
        'remove inmemoryfeaturelayer features
 
        highlightFeatureLayer.Open()
        'highlightFeatureLayer.FeatureSource.Open()
        If highlightFeatureLayer.InternalFeatures.Count > 0 Then
 
            highlightFeatureLayer.InternalFeatures.Clear()
        End If
        'highlightFeatureLayer.FeatureSource.Close()
        highlightFeatureLayer.Close()
        highlightFeatureLayer.Name = “Teacher Lee”
 
 
        'highlightFeatureLayer = New InMemoryFeatureLayer
 
        Select Case (shapeType)
            Case ShapeFileType.Point
                highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.GhostWhite, 8, GeoColor.StandardColors.Black)
            Case ShapeFileType.Polygon
                highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.GhostWhite, GeoColor.StandardColors.Black, 3)
            Case ShapeFileType.Polyline
                highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.StandardColors.GhostWhite, 3, True)
 
        End Select
 
        highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        'highlightOverlay = New LayerOverlay
        'highlightOverlay.Name = “HighlightOverlay”
        highlightFeatureLayer.Open()
        'highlightFeatureLayer.FeatureSource.Open()
        highlightFeatureLayer.FeatureSource.BeginTransaction()
        highlightFeatureLayer.FeatureSource.AddFeature(newFeature)
        highlightFeatureLayer.FeatureSource.CommitTransaction()
        'highlightFeatureLayer.FeatureSource.Close()
        highlightFeatureLayer.Close()
 
        highlightOverlay.Layers.Add(highlightFeatureLayer)
        WpfMap_Main.Overlays.Add(highlightOverlay)
 
        'WpfMap_Main.Refresh()
 
        originalTransferValueFeature(2) = shapeType
 
        Console.WriteLine(“highlight feature created”)
 
 
 
    End Sub

 In AttributeTransfer.vb/ReselectJoinFeature:


Private Sub ReselectJoinFeature(ByVal sender As ObjectByVal As ThinkGeo.MapSuite.WpfDesktopEdition.MapClickWpfMapEventArgs)
        Dim newJoinFeature As Feature
        newJoinFeature = New Feature
        Dim transferResults() As Object
 
        'select the new feature, change the highlight layer
        newJoinFeature = SetNewJoinFeatureValue(e)
        If newJoinFeature IsNot Nothing Then
            'checkfortransfervalues
            transferResults = CheckForTransferValues(activeLayer.Name, valueTransferCollection(0).Name, newJoinFeature)
            If transferResults(4) <> “” Then
                valueTransferResult = transferResults(4)
            Else
                valueTransferResult = “”
            End If
            Console.WriteLine(valueTransferResult + “: value transfer result & at the end”)
        Else
            Console.WriteLine(“reselectjoinfeature is nothing”)
        End If
        WpfMap_Main.Refresh()
    End Sub

Hope it works for you.

Regards,

Johnny

 

Johnny…  It looks like it is working.  I didn’t think about concurrent refreshing being an issue until I made the followup post.   
  
 On a side note, I noticed when I zoom in and out quick that I get a System.ObjectDisposedException saying it Cannot access a closed Stream.  I assume that has to do with the grabbing and releasing of the tiles for the basemap or layers.  Is there a way to prevent that exception or catch it at least?  Would it be something I could adjust the DrawingExceptionMode property for the overlays?  Although it doesn’t make sense why you would zoom in and out like that, I would like to prevent a possible crash.

Hi Brandon, 
  
 Good to hear your previous issue have been solved. 
 As for the second issue, sorry to say we didn’t recreate the issue with your sample. I just guess if there is anything differences between the sample you send to us and yours? may be you can send us another sample which can recreate the issue, once it is recreated, I think that would be easy for us to figure it out. 
  
 Regards, 
 Johnny

Hi Johnny,



I was just using the sample I provided, and I was able to get the exception again.  Basically, I am using the mouse wheel to zoom in and out quickly.  It only took me a few seconds of doing that to prompt the exception.  I was able to get it to crash also just using the zoom bar on the map too although it took a little longer.



I think it might have something to do with using the GoogleMaps basemaps.  I tried it on one of your samples, and it did not crash on me, but that sample was using the WorldMapKit instead of GoogleMaps.  We are using a tile cache for the GoogleMaps basemaps so it is possible that there is an issue when I am doing the quick zooming that the program is trying to access a resource that was disposed of when the zoom level changed.



Is there a way to override the drawing methods for tiled basemaps that would either allow us to account for rapid zooming and accessing disposed objects?

Hi Brandon,



Sorry to say, we still can’t recreate the crash after trying different machines. here is out test video: screencast.com/t/2xgXDBokPoJR



But what I guess is there might be something related with the Google cache, would you please try to comment out the cache part for GoogleMapsOverlay or try the below codes:


Dim googleOverlay = New LayerOverlay()
Dim googlelayer = New GoogleMapsLayer()
googlelayer.MapType = GoogleMapsMapType.Terrain
googleOverlay.Layers.Add(googlelayer)
googleOverlay.TileCache = New FileBitmapTileCache(cacheDirectory)

instead of 

googleOverlay = New GoogleMapsOverlay(cacheDirectory, “”, “”)



Hope it helps.

Regards,

Troy

Troy…  I made the adjusts you recommended, and I am still crashing.  I have attached a screen capture (sorry it gets blurry a bit), and included screenshots of the exception I am getting.  



For the GoogleLayer and all my ShapefileFeatureLayers, I tried adding DrawingExceptionMode.DrawException to each of them to at least show me pink tiles if it were having issues there, and I still crashed.



Any further advice?  Although it is unlikely someone would be zooming like I was doing in the video, I cannot dismiss the possibility so I would like to figure this out further.  Thanks!

ThinkGeo_ClosedStreamException.zip (1.08 MB)

Hi Brandon,



Sorry to say we didn’t encounter such issue before. Since it happens on in Googlelayer, I suggest you can switch to BingMapLayer to see if owns the same crash. 


Actually, I am not sure if it is related with request count limit for Google Sever, but normally, the error always will throw out with a 403 error. Any way, as you are using the GoogleMapsLayer or GoogleMapsOverlay with a default constructor which means the limit request count is very less, I advice you use the other ways to increase the count of valid request like with an ApiKey.
More details please refer to thinkgeo.com/forums/MapSuite…fault.aspx in the 4th answer.



Hope it helps.

Regards,

Troy

Troy…  I have gotten the 403 Forbidden exception before, but this one still comes up separate.  I have run through with the GoogleMaps Overlay commented out and still gotten the exception.  I was just curious if there is a way to capture that exception or prevent it without running the whole app.run through a try/catch.  If you happen to hear or see anything about this, please pass it along.  I will keep testing to see what I can find out.

Hi Brandon, 
  
 So, you are not care the 403 error but just the crash one. But sorry, no matter how I play with the sample you gave to me, the crash never show up. 
  
 In my eyes, if the crash is caused by some tiles drawing, we can set the DrawingExceptionMode property should catch or ignore the exception from it, like the below codes: 
  
        Dim googleOverlay = New LayerOverlay()
        googleOverlay.DrawingExceptionMode = DrawingExceptionMode.DrawException
        Dim googlelayer = New GoogleMapsLayer()
        googlelayer.MapType = GoogleMapsMapType.Terrain
        googleOverlay.Layers.Add(googlelayer)
        googleOverlay.TileCache = New FileBitmapTileCache(cacheDirectory)
 
  
 BTW, set the google overlay as singleTile might be helpful to catch the exception for more details as single tile didn’t use the multithread to draw the tile. 
  
 Hope you can find more details on it. 
 Thanks, 
 Troy

Hi Brandon, 
  
 May be you can try to register the DrawingException event on the LayerOverlay to see if it can catch the exception. 
  
 Thanks, 
 Troy