ThinkGeo.com    |     Documentation    |     Premium Support

Unhandledable System.NullReferenceException

 I upgraded the MapSuite dlls from 4.5.something to 5.0.159 this week.


 Frist thing I noticed is the general speed improvement. Map is faster now. I'm happy with it. But at the same time I'm getting a very odd NullReferenceException while loadin the data/refreshing the screen even thought I have an Application_DispatcherUnhandledExceptionFilter that does not catch it. Visual Studio can't just tell me the reason of the problem and the stack trace does not show anything (at least to me)


 All this happens the second time I refresh the data, not the initial one, and If I set the Overlay DaweingException to Draw, I see tiles with the cross that gets OK later in the refresh process


 Does this stack trace have any sense for you?



System.NullReferenceException was unhandled


  Message=Referencia a objeto no establecida como instancia de un objeto.


  Source=WpfDesktopEdition


  StackTrace:


       en ThinkGeo.MapSuite.WpfDesktopEdition.Tile.DrawException(GeoCanvas geoCanvas, Exception exception)


       en ThinkGeo.MapSuite.WpfDesktopEdition.Tile.Draw(GeoCanvas geoCanvas)


       en ThinkGeo.MapSuite.WpfDesktopEdition.Tile.tBM=(Object tRM=)


       en System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)


       en System.Threading.ExecutionContext.runTryCode(Object userData)


       en System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)


       en System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)


       en System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)


       en System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()


       en System.Threading.ThreadPoolWorkQueue.Dispatch()


       en System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()


  InnerException: 



 


 



Hello Carlos, 
  
 Sorry I can’t find the root cause from these stacktrace, could you please provide some code where throw the exception? 
  
 Thank you for your help. 
  
 Regards, 
  
 Gary

Found it!! 
  
  With 4.5 engine I used to perform a InmemoryFeatureLayer.InternalFeatures.Clear when updating, then add all the new Features and finally call InmemoryFeauteLayer.BuildIndex() 
  
  It turns out that your Tile.Draw() internal code does not like it anymore in version 5.0. Calling .BuildIndex just after clearing internal features just solve the problem. 
  
  Obviously you did change something internally, but shouldn’t InternalFeatures.Clear call BuildIndex if it is strictly necessary?

Hello Carlos, 
  
 Sorry I don’t think we made any changes in Interfeatures.Clear. 
  
 And one thing is we recommend to use EditTools instead of InternelFeatures, you can have a try. 
  
 Regards, 
  
 Gary

Carlos, welcome back.  Where have you been? 
  
 This is a weird problem you are experiencing as I am doing the same thing as you, but there are no exceptions being thrown, unless I am swallowing them somewhere. 
  
 Gary, why do you recommend we use EditTools instead?  Is there some little performance to be gained?

Hi Klaus is nice to read you again ;) 
  
  I’ve been working on other projects for the last months, and I’m retaking this now. 
  It’s weird as you say, because VS do not pop the exception at any specific place, it’s like its being thrown in other thread from which I don’t have the source, what makes sense, as the stack trace locates it in the Tiles.Draw() 
   
   I’ve been clearing InternalFeatures before refilling it with new ones for finally BuildIndex for six months without problems, but just after upgrading the engine from 4.5 to 5.0 this exception pops up all the times. 
   Including a RebuildIndex just after the InternalFeatures.Clear() seems to solve the problem. But I found it by mere try and error debugging. As It happen before to me, even the Exception filter does not catch it in any way. It’s frustrating. 
  
  Gary, I was going to ask you the same, why EditTools? 
  


Hello Carlos and Klaus, 
  
 There are two reasons to use EditTools instead of InternelFeatures. 
  
 First, a layer contains FeatureSource, FeatureSource contains collection of Features, InternelFeatures is directly operate the Features collection, then if you set the projection to the FeatureSource, InterlFeatures visit the source data, but the EditTool will visit the data after projection filter. 
  
 Second, if a layer have built the index file, then you add feature using InternelFeatures, it will missing in the index file, but if you use EditTool, the comittranscation function will automatically build the index file, then you can have the newest one. 
  
 Regards, 
  
 Gary

 Gary, thanks for the response.


 
This is the logic I currently have to update my layers.
 

 lock (InternalFeatures)
                           {
                               InternalFeatures.Clear();
                               InternalFeatures.AddRange(featuresToAdd);                            
                           }

                           if (InternalFeatures.Count > 0)
                               BuildIndex();

 
Please advise on how I should change this logic to use EditTools as it does not support a Clear operation.
 
Thanks again.

Hello Klaus, 
  
 First you can still use the InternalFeatures.Clear(), this is fine, then you need use inMemoryLayer.EditTools.BeginTransaction(), now loop your featuresToAdd collection and add feature into using inMemoryLayer.EditTools.Add() one by one, at the end inMemoryLayer.EditTools.CommitTransaction(), it will buildindex automatically. 
  
 Regards, 
  
 Gary

 Posted By Gary on 10-26-2011 02:25 AM 

… a layer contains FeatureSource, FeatureSource contains collection of Features, InternelFeatures is directly operate the Features collection, then if you set the projection to the FeatureSource, InterlFeatures visit the source data, but the EditTool will visit the data after projection filter. 


  

  Hi Gary,


I’m sorry, but I don’t get the point. What we are adding to the InternalFeatures is really the source data, not the projected one. I would use EditTool for instance to modify a feature by draggin it (as it’s projected), but the Features I get from my database are source data lat/lon so given your explanation they would better fit on InternalFeatures. I always rebuild the index after adding them (and now after clearing the collection)


 Anyway this do not explain why I’m gettng a NullReferenceException from your TileDraw core, but it do not happen if I build the index just after clearing the InternalFeatures


 And the worst thing is that there is no way to catch the exception, the only workarround is to set the Overlay’s DrawingExceptionMode to DrawException. This way red X appears on the tiles containig features during the load process, and gets solved after the final BuildIndex, but at least the application do not die. How do you catch the exceptions if DrawingExceptionMode.DrawException is enabled?



Hello Carlos, 
  
 Projection is just one part, another part let us recommend the Edittools is the index, user will forget to rebuild the index sometime, so the edittools will made this automatically, that’s a reason, if you can rebuild it every time, it’s the same result. 
  
 For your question, because I can’t recreate it, so I have some guesses, 
  
 1) In the GetFeaturesInsideBoundingBoxCore function, it will  check the rTree(index), if the rTree == null or rTree.Count <= 0, it will loop your internalFeatures and get all features to judgement. But if the rTree >0, it will get the features only including in the rTree, sometimes this will cause problem because you are searching for something not in the rtree. 
  
 2) If you rebuild the index after clearing the InternalFeatures, so the rtree will be 0, it will loop your internalFeatures, then it can find everything you have. 
  
 Sorry this just some guesses, if the problem is still boring you, please provide a sample that we can find the root cause for you. 
  
 Regards, 
  
 Gary

Hi Gary, 
  
  I don’t know why in my application Visual Studio fails to catch the NullReferenceException, and do not locate the point within the code where the exception was thrown. Anyway, when trying to create a single demo I found that by simply adding a Feature to InternalFeatures and then calling Refresh before BuildIndex call throws the exception.  
  First thing it comes to the mind is “ok, then do not call refresh until you build the index”, but it turns out to be a challenge, as refresh might be called from other thread of the application, and sync lock the whole layer internal features while loading Features would lock the application for quite a long time. 
  Wouldn’t it make sense to have a try-catch block inside the Draw core, so in case of an incomplete rTree it just don’t crash (obviously nor find features spatially) 
  
 Carlos

Hello Carlos, 
  
 BuildIndex is not have to do, index will help you searching faster, but without this we still can work, this problem is weird, could you please provide some code, I can try to find the error. 
  
 Regards, 
  
 Gary

Hi Gary, 



I'm having troubles to recreate the issue today in order to create a simple demo, but in the attempt I found two issues: 



1) If I try to refresh an overlay before WpfMap1 is refreshed for the fist time, I get the null reference exception. This is more or less understandable, even it should not happen anyway 

2) I get other exception with the sample code I'm attaching 



I'll keep trying to create a simple demo showing the issue with the Index. It's quite complex to extract simple demos from the full application.



Demo.zip (50.2 KB)

Hello Carlos, 
  
 Thanks for your sample, that helps a lot, I can recreate the problem with it. 
  
 The reason is like I said, when you clear your internal features, the features removed but their info still exist in the index, if you didn’t rebuild the index, program will searching the index and get the feature info, but for now, the feature has removed. So it will throw the exception. 
  
 Regards, 
  
 Gary

I understand it, but it creates a problem in multithreaded applications where one thread would be updating the FeatureLayer while other is calling Refresh after certain update. 
  
   It should just fail the spatial search (i.e FindFeaturesNearestTo will not work), but not thread an exception, shouldn’t it?

Hello Carlos, 



The exception reason is complex, it will throw exception by some other mechanism,  but you are right, it should not make all threads failed, our WPF edition didn't handle this, could you please try to add the code below in your app.xaml.cs file to handle the exception? 


public partial class App : Application
    {
        public App() {
            DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
        }

        void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
        }
    }



Please let us know if it's still not working. 



Regards, 



Gary



Hi Gary, 
  
  It’s not possible to inherit from Application in VB (I’m sure I missing something really silly) 
  
 Partial Public Class App 
   Inherits Application 
  
   Public Sub New() 
     AddHandler Windows.Threading.Dispatcher.CurrentDispatcher.UnhandledException, New System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(AddressOf App_DispatcherUnhandledException) 
   End Sub 
  
   Private Sub App_DispatcherUnhandledException(ByVal sender As Object, ByVal e As System.Windows.Threading.DispatcherUnhandledExceptionEventArgs) 
     e.Handled = True 
   End Sub 
 End Class

Ok, it was silly indeed. References to System.Windows.Application and System.Windows.Forms.Application was conflicting. 
  
  I’ll try the workaround. Will this be fixed for 6.0?

Hello Carlos, 



Could you please try this code below: 


    Partial Public Class App
        Inherits System.Windows.Application

        Public Sub New()
            AddHandler System.Windows.Threading.Dispatcher.CurrentDispatcher.UnhandledException, New System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(AddressOf App_DispatcherUnhandledException)
        End Sub

        Private Sub App_DispatcherUnhandledException(ByVal sender As Object, ByVal e As System.Windows.Threading.DispatcherUnhandledExceptionEventArgs)
            e.Handled = True
        End Sub
    End Class



And I don't know if it will doing some changes in next release, I will confirm it. 



Regards, 



Gary