ThinkGeo.com    |     Documentation    |     Premium Support

Projection not open

Good Morning (at least in NM, it's morning! :))


I downloaded the latest version of the software (3.0.362) this morning. Thank you for putting out the new version. I've run into an issue I had seen before. I've seen it in both single threaded and multi threaded mode.


Invalid Operation Exception: The projection is not open. Please open it before calling this method.


Both times I got this error this morning were after having the map open and not using it for several minutes. As soon as I click back on the map to zoom or anything, this error comes up.


Here is the stack trace.


"   at ThinkGeo.MapSuite.Core.x6d719af406ea4c2c.xed94929c048fbff7(Boolean x40fc51452dedaf8a)\r\n   at ThinkGeo.MapSuite.Core.Projection.ConvertToInternalProjection(RectangleShape rectangleShape)\r\n   at ThinkGeo.MapSuite.Core.FeatureSource.ConvertToInternalProjection(RectangleShape rectangle)\r\n   at ThinkGeo.MapSuite.Core.FeatureSource.GetFeaturesForDrawing(RectangleShape boundingBox, Double screenWidth, Double screenHeight, IEnumerable`1 returningColumnNames)\r\n   at ThinkGeo.MapSuite.Core.FeatureLayer.DrawCore(GeoCanvas canvas, Collection`1 labelsInAllLayers)\r\n   at ThinkGeo.MapSuite.Core.Layer.Draw(GeoCanvas canvas, Collection`1 labelsInAllLayers)\r\n   at ThinkGeo.MapSuite.DesktopEdition.LayerOverlay.DrawCore(GeoCanvas canvas)\r\n   at ThinkGeo.MapSuite.DesktopEdition.Overlay.Draw(GeoCanvas canvas)\r\n   at ThinkGeo.MapSuite.DesktopEdition.WinformsMap.x5e1f8125aa040824(Object x2680f14bfcc5c488)\r\n   at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)\r\n   at System.Threading.ExecutionContext.runTryCode(Object userData)\r\n   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)\r\n   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)\r\n   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)"


Can you give me some direction? Are we just supposed to open the projection and leave it open the whole time? This doesn't seem right to me, but please if you could explain the expected behavior on this, I'll try what I can. I have several different projections currently. I'm in the process of moving most everything to only one projection (or at least much fewer), but currently I have several based on different data sources.


Thanks!


Kimberly



Kimberly,


How many projections are you trying to create? Did you create many projections with same SRIDs? I suggest you trying not to use the same shard Projection instance for many layers if they shared the same projection SRIDs.  See more details in following post:
gis.thinkgeo.com/Support/Dis....aspx#9530
 
 
There would be potential problem for this because we use another threading to draw, in which it will close the projection while some other layers may be trying to use it. See more details in following post:
gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/12/aft/5170/afv/topic/afpgj/1/Default.aspx#5875
 
If possible, can you send us a demo which probably recreates this problem; we will review the codes and test against it.
 
I know you are upset by this problem for a long time, sorry for the inconvenience.
 
Let me know if you still have any questions.
 
Thanks.
 
Yale

I’ve bumped into this, too.   For now, I just have code that opens projections all over the place, if I use shared projections.   I’m not sure I understand the logic of opening and closing projections, anyway.    
  
 We use the world map kit.  I cringe at the though of having to create 300 identical projections, rather than share a single projection. 
  
 In your logic, should you not be checking to see if a projection is open, and if previously opened, do not close it?

I’m sorry, but I’m confused. The first link you gave shows an example where you create a single instance of a projection and assign it to multiple layers and you claim that this works. And then in your next post you say that if you create multiple “same” projections, you get an error and your example there has multiple calls to new. However, in the text of your message, you recommend that I try not to use a single shared projection instance. This seems to go directly against the advice above. The second article you post makes sense and I hadn’t really been using projections in that way, so that’s a bit confusing. I think I’ll look at my code from that point of view to see if I can work on that. However, I still need to know if using a single shared instance of a projection is going to cause me grief. Can you tell me that? I agree with Ted that having many (not 300 in my case) identical projection instances seems like a bad idea and I hate the idea of spreading projection.open calls around my code.  
  
 Finally, I don’t want to send you a demo. If I knew exactly what was causing the issue, I would tell you that. And I can’t send you my entire project. What I would prefer is for you to TEACH me the proper way to utilize projections. (I think the second link in your post is probably very close to that.) If I understood the expected use of the projections and I still had this problem, I would be in a much better position to send you a small example.  
  
 There’s some quote about teaching a man to fish that comes to mind about now. 
  
 Thanks, 
 Kimberly

Posted By Yale on 07-27-2009 01:19 AM 

Kimberly,


How many projections are you trying to create? Did you create many projections with same SRIDs? I suggest you trying not to use the same shard Projection instance for many layers if they shared the same projection SRIDs.  See more details in following post:
gis.thinkgeo.com/Support/Dis…aspx#9530
 
 
There would be potential problem for this because we use another threading to draw, in which it will close the projection while some other layers may be trying to use it. See more details in following post:
gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/12/aft/5170/afv/topic/afpgj/1/Default.aspx#5875
 
If possible, can you send us a demo which probably recreates this problem; we will review the codes and test against it.
 
I know you are upset by this problem for a long time, sorry for the inconvenience.
 
Let me know if you still have any questions.
 
Thanks.
 
Yale


Kimberly & Ted,
 
I am so sorry I made a critical mistake in my previous post, what I want to suggest is “trying to use the same shared projection instance for many layers if they shared the same projection SRIDs”, but in my previous post, but I typed it into “trying not to …”, in completely wrong directions.
 
I am sorry for the inconvenience and misunderstanding.
 
Thanks.
 
Yale





 



Kimberly, 
  
 I think the root reason for this problem happening is because when we do any query from a layer, we will use the projection if we set it while the projection is closed by some unexpected behaviors. 
  
 There are couple of reasons to closed the projection which is expected to be open, so basically the easiest way is to keep the projection open unless the application is ready to quit, and this open projection will not take too much resources and it will not cause any serious bitmap like memory growing just like bitmap not disposed correctly. Even thought, I still DONOT think it is a good programming habit as you said. 
  
 Any more questions just let me know. 
  
 Thanks. 
  
 Yale 


 


Yale,


This projection "not opened" is a nightmare; new with 392:


Somewhere in my code, I've to do:

Layer.FeatureSource.Open();

Layer.FeatureSource.BeginTransaction();

...

Layer.FeatureSource.CommitTransaction();

Layer.FeatureSource.Close();


Guess what .... Layer.FeatureSource.Close() closes Layer.FeatureSource.Projection.


Then the next redraw raises a "projection not opened" exception


How to proceed ?


Patrick.


Yale,


This projection "not opened" is a nightmare.


Somewhere in my code, I've to do:

Layer.FeatureSource.Open();

Layer.FeatureSource.BeginTransaction();

...



afp.Layer.MSMainLayer.FeatureSource.Close();


 



I really wish the whole concept of opening and closing projections would go away.    I don’t understand the significance of potential resource savings by using the open/close concept.   And I think it is definitely a problem when there are places in MapSuite code that close projections that I already have open.

Any progress ? 


I think if you close the layer, it closes the projection also. 
 I do not know what the best way is, but I did an If not projection.IsOpen then projection.Open

Guys, thanks for your post and I am so sorry for the delay, now we are busy on the new public release which targets at better performance and better stability. 
  
 About the Open & Close introduced in the MapSuiteCore, its basic concept and idea is from the stream of .net, it seems it will cause many problems when it is multi-access especially in multi-threaded mode. 
  
 I think Alta suggestion is a way to go around the problem even though it is not the best. 
  
 Sorry for the inconvenience now. 
  
 Any more questions please feel free to let me know. 
  
 Thanks. 
  
 Yale 


Hello,  
  
 This still occurs in 3.0.410; in the same condition that I explain 3 posts upper. 
  
 Regards,  
 Patrick.

Guys, 
  
   I wanted to chime in on the projection closing issue and give you some background on this. 
  
   The reason for having an open and close on the projection class itself is very similar to the open and close on many of our object including layer, feature source, etc.  The logic is that these objects may have managed or unmanaged resources that need to be cleaned up after they are used.  For example the Proj4Projection has unmanaged resources that need to get released.  You can call the close on the instance when you are no longer using them and the resources can be released properly and can be reclaimed.  It is very similar to the dispose and in fact an alternate to it in the Microsoft API guidelines.  With dispose, a well behaved object releases its resources and calls the dispose on other objects in its hierarchy.  In the case of the Open method you may have large up front creation costs and we want you to be able to control exactly when it happens.  We had considered always trying to open before we use the instance but that would create more subtle problems like when you think something is closed then you have some stray code that re-opens them and you have no idea.  These resources never get released and problems ensue.  In the way we have it now you control whenever they are opened and closed explicitly. 
  
   The issue is that you are using references to the projection instance in many other classes instances.  This is the case with any other kinds of objects that implement dispose properly.  You need to be aware that once you put the projection in two classes they have no idea that this is a shared resource.  Anytime you start to sprinkle around references between objects you are bound to run into issues like these especially with classes that should be disposed or closed.  A good class design will dispose of any children it has that support it.  This is the model we work from.  The only difference is that with dispose you can never come back, where with an open and close model you can do it at as many times as you need.  This was also a need  for serialization. Before we serialize a layer you need to close it to release any unmanaged resources and then you can serialize then deserialize and open the object.  This was required for things like SQL Server State in the web environment.  
  
   There are a few things I would suggest you can do if you want to reuse the same classes between many layers.  The first would be to not re-use the projection class in places where it can be avoided.  If you go through all the trouble of somewhere in your code creating a new layer, or a new feature source for short term use then create a new projection.  If you know this will be trouble then re-open the projection after operations you know will close it. If instead you index into the current stack of layers on the map and edit like in a previous post then do not close the feature source.  Also on the Layer’s next open the projection.open will also get called.  By sharing this kind of class it puts some responsibility on you to know its state across all of the places you put it. 
  
   Another way if you have shared projection classes when you just need the class on a layer or feature source temporarily then before you call the close set the projection property to null on the feature source.  This will unhook the reference and the close will not trigger the projection close for all of the other places you use it. 
 Having said all of this and if you are still reading this post then let me say it should be easier than the ideas above.  I understand that people have hundreds of layers and it should be easier to keep track of and to use it.  What I would personally really rather do is to inherit from the Proj4Projection class, or whatever projection class you need, and override the close to stop it from closing.  The problem is, if anyone has tried, is that you cannot stop the IsOpen property from being set to false through inheritance.  The IsOpen = false flag is set in the concrete method after the CloseCore is closed.  I think in hindsight this was a bad idea.  What I am going to do to support this feature is to change the place we internally set the IsOpen flag to before the CloseCore and then expose a protected Set on the IsOpen so you can turn it back to Open if you want to bypass the CloseCore.   I would then create a SharedProj4Projection class and override the close to have it skip the closing.  Next I would create something like a CloseForReal method that called the Base.CloseCore when I really wanted to close it. I would also like to do the same thing to all of the objects that support the open and close system. 
  
   Let me know if you have any questions or would like further information on this stuff.  BTW we will put this in for the Monday release. 
  
 David 


David, 
  
 my 2 cents: 
  
 I do not share projection and the main issue (for me) is that featuresource.close is closing featuresource.projection behind the scene. 
 The result is that when you edit a layer with open, begintransaction, committransaction, close … then the projection becomes closed … then your drawing core raise the exception “projection is not open” … so basicaly, from my point of view, MS raise an exception on a projection that it closed itself. 
  
 Another issue with non shared projection is that if you use more than 100 then we get an exception on their dispose; please see the example I’ve provided in gis.thinkgeo.com/tabid/143/aff/21/afv/topic/aft/6245/afc/11045/Default.aspx 
  
 Hope this helps, 
 Patrick.

Patrick, 
  
 thanks for more detail.  I was kind of addressing you and Ted and everyone else.  I wanted my comments as general as possible.  To your issue the problem is you are closing the featuresource.  We created the featuresource internally and we expect it to be open.  I would suggest you close the layer instead.  I think we check that I’m the desktop control and reopen it if closed.  That should solve your issue.  
  
 On the 100 projections this is most likley due to the unmanaged library we are using.  This is not an inherant limitation of the projection system but of proj4 itself.  In this case sharing them would help and the shared class I proposed would do the trick. 
  
 Sorry for any mistakes as I am doing this post from my mobile phone. 
  
 David

Dear David, 
  
 I’m opening and closing the featuresource because it’s done that way in your sample; gis.thinkgeo.com/tabid/143/aff/21/afv/topic/aft/5882/afc/9193/Default.aspx 
  
 I’m experiencing the same issue if I close the layer instead of closing the featuresource. 
  
 I think that if you fix these 2 closing issues and implement the sharedProjection then we’ll have something working here. 
  
 Thank you, 
 Patrick.

Patrick, 
  
   FYI - The changes to allow us to create a SharedProj4Projection are going in today.  Also I looked at the sample you mentioned for the FeatureSource.Close and that sample is a bit different from what you described because in that sample they are creating a FeatureSource that stands alone without a layer.  In that case it is fine, I think you were going into on on a live layer and that is kind of a no-no.  We checked the code and when we drawn an overlay we check to see if the layer is open and if not we open it so closing at the layer level should be fine is you call a refresh after it.  Maybe there is another spot before that which is causing the error.  Could you send me a stack trace if possible.  Also do you know if you are in Single or Multi threaded mode?  You can check using the ThreadingMode property on the map.  Try in single threaded and see what happens if you find you are in MultiThreaded mode.  The other issue is you are in multi threaded mode is that maybe you are not locking the overlay and it may be drawing at the same time.  It seems you responded late in the evening and if you are around now maybe we could setup a goto-meeting so I can see the issues in real-time and check out your code. 
  
 David

David, 
  
 maybe I missed something, but with 415 (x86 built on x64 machine) that code 
  
 Console.writeLn ((m_MSMainLayer as FeatureLayer).FeatureSource.Projection.IsOpen); 
 MSMainLayer.Close(); 
 Console.writeLn ((m_MSMainLayer as FeatureLayer).FeatureSource.Projection.IsOpen); 
  
 displays 
 true 
 false 
  
 This means that layer.close closed the projection. 
  
 then the following refresh raise the exception.

Patrick,


Sorry for that. Our solution is to create your own customized Projection, following code is the reference.

    public class SharedProj4Projection : Proj4Projection
    {
        public SharedProj4Projection()
            : this(string.Empty, string.Empty)
        { }

        public SharedProj4Projection(string internalProjectionParametersString, string externalProjectionParametersString)
            : base(internalProjectionParametersString, externalProjectionParametersString)
        { }

        public SharedProj4Projection(int internalEpsgSrid, int externalEpsgSrid)
            : base(internalEpsgSrid, externalEpsgSrid)
        { }

        protected override void OpenCore()
        {
            base.OpenCore();
        }

        protected override void CloseCore()
        {
            IsOpen = true;
        }

        public void ForceClose()
        {
            base.Close();
        }
    }

 

And set it like this:

InMemoryFeatureLayer layer = new InMemoryFeatureLayer();
layer.FeatureSource.Projection = new SharedProj4Projection(Proj4Projection.GetEpsgParametersString(4326),Proj4Projection.GetGoogleMapParametersString());

 

Any more questions please feel free to let me know.
 
Thanks.
 
Yale



I have release 3.1.247 and this is still an issue. 
  
 - I tried 1 Projection shared amongst all. "Projection not open" 
 - I tried 1 Projection for each.  "Projection not open" 
  
 Unfortunately, it is impossible to "open the Projection" because this is all happening behind the scenes when the map starts rendering, and nowhere in the documentation does it state that a Projection needs to be "Opened".  It seems more like "Set and Forget". 
  
 - The above workaround, creating a SharedProjection, did work.  However, it would be preferable to be able to put something together without workarounds.