Change Tabs creates Unstable Map Providers. (Memory Leak)

4 posts, 0 answers
  1. Don
    Don avatar
    3 posts
    Member since:
    Jul 2012

    Posted 13 Sep 2018 Link to this post

    I am finding:
    1) Create a PAGE, and VIEW MODEL
    2) ON the Page:
    Add a Tab Control with TWO Tab Items, on each Tab Item add a RadMap and a ComboBox
    3) In the VM Create an Observable Collection of Providers and assign to both Combo Boxes on each Tab Item.
    4) In the VM create a property(INotifyPropertyChanged) for each SELECTED Provider from each ComboBox, and BIND the Provider to each Map's Provider Dependency Property. (One List / Two Selected Items /Two Maps)
    5) Run the App, switch between the Tabs and switch between the ComboBox's Selected Provider and you get botched providers displaying mixed data.
    I have determined that when tabbing from one TabItem to an other, the RadMap gets Unloaded and then Reloaded each time, and several resources gets messed up because you do not call the DISPOSE. But, in fact you cant or else you would not be able to tab back... so there are several additional week references that are not detached and memory will continue to leak leading to poorly managed provider tiles etc...  Either that, or there are static references in both Maps reference... That I am not sure yet, still investigating and leaning on the Provider itself.

    Has anyone else seen bad behavior on the RadMap with multiple Providers Binding on several Tabs?

    thanks,

    Don

     

  2. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3142 posts

    Posted 18 Sep 2018 Link to this post

    Hi Don,

    Generally a single RadMap provider is not designed for simultaneous usage in multiple RadMap instances. We reproduced the issues you described (and some exceptions) with simple setup with no viewmodels:
    this.combo1.ItemsSource = this.combo2.ItemsSource = new ObservableCollection<MapProviderBase>()
               {
                   new OpenStreetMapProvider(),
                   new ArcGisMapProvider() { Mode = ArcGisMapMode.Terrain },
               };
    2 RadMap Instances in 2 TabItems have their Provider property bound to the SelectedValue of the corresponding ComboBox. Issues start when both maps have the same provider.
    RadMap and Map providers are IDisposable but we do not call the dispose method in the Unloaded event of the Map. This is a WPF framework responsibility (calling Dispose) and generally unloading a control doesn't mean no other controls or classes have live reference to the unloaded control. To dispose map or the providers you can call the Dispose function manually. For example in this scenario, we successfully solved the issues with Unloaded event handler and the Dispose code (which is part of the Map's Dispose):

    private void RadMap_Unloaded(object sender, RoutedEventArgs e)
           {
               RadMap map = sender as RadMap;
               if (map != null)
               {
                   foreach (object item in map.Providers)
                   {
                       IDisposable provider = item as IDisposable;
                       if (provider != null)
                       {
                           provider.Dispose();
                       }
                   }
                   map.Providers.RemoveAll();
               }
           }

    When maps are reloaded , however, you need to assign the selected provider again. That is why we basically encourage you to use separate models and separate providers for separate views:
    this.combo1.ItemsSource = new ObservableCollection<MapProviderBase>()
                {
                    new OpenStreetMapProvider(),
                    new ArcGisMapProvider() { Mode = ArcGisMapMode.Terrain },
                };
     
                this.combo2.ItemsSource = new ObservableCollection<MapProviderBase>()
                {
                    new OpenStreetMapProvider(),
                    new ArcGisMapProvider() { Mode = ArcGisMapMode.Terrain },
                };


    Regards,
    Petar Mladenov
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. Don
    Don avatar
    1 posts
    Member since:
    May 2017

    Posted 18 Sep 2018 in reply to Petar Mladenov Link to this post

    Can you explain it in MVVM terms? this is code behind.

    I m using MVVM, once you dispose of the Providers in code behind, you have lost BINDING of the provider.

    How do you support MVVM?

    Thanks,

    Don

  4. Petar Mladenov
    Admin
    Petar Mladenov avatar
    3142 posts

    Posted 20 Sep 2018 Link to this post

    Hi Don,

    Yes, with the dispose approach binding is lost in order to improve the memory and the single instance of provider being used by multiple map instances. Please consider such scenarios as not supported in RadMap - multiple maps using single provider. To preserve MVVM pattern, I encourage you to use the second approach with separate models for the separate comboxes:

    this.combo1.ItemsSource = new ObservableCollection<MapProviderBase>()
                {
                    new OpenStreetMapProvider(),
                    new ArcGisMapProvider() { Mode = ArcGisMapMode.Terrain },
                };
     
                this.combo2.ItemsSource = new ObservableCollection<MapProviderBase>()
                {
                    new OpenStreetMapProvider(),
                    new ArcGisMapProvider() { Mode = ArcGisMapMode.Terrain },
                };


    Regards,
    Petar Mladenov
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Back to Top