This is a migrated thread and some comments may be shown as answers.

BingMapProvider memory leak and exceptions

4 Answers 61 Views
Map
This is a migrated thread and some comments may be shown as answers.
Jeroen
Top achievements
Rank 1
Jeroen asked on 07 Feb 2014, 04:19 PM
It seems that the BingMapProvider has a few problems that cause memory leaks.

Please find some sample code below.
My sample application basically contains a grid to which I add a 'MapWrapper' control. Every 3 seconds, the MapWrapper is removed, and a new MapWrapper is added.
The MapWrapper is a simple control that contains a RadMap.

There are two buttons shown on top of the MapWrapper.
The first button allows to turn on/off the 3-second timer.
The second button allows to switch between a BingMapProvider and an OpenStreetMapProvider. Every time a new MapWrapper is instantiated, a provider of the chosen type is set as provider for the RadMap.

Letting the application run for a while using OSM, there are no problems.
However, when using the BingMapProvider, two problems occur:

1) Not a single instance of BingMapProvider is ever released, and this creates a huge memory leak, especially in our live application where the Map control has several layers of data.
(OpenStreetMapProvider objects on the other hand are always removed -- even without any custom implementation of Dispose)

2) Frequently and irregularly, WinDbg shows the following two lines while creating the BingMapProvider:
(604.c74): CLR exception - code e0434352 (first chance)
(604.1868): CLR exception - code e0434352 (first chance)
Every time that this exception occurs, the map simply fails to show anything.

Both problems are huge game breakers and prevent us from using Bing in our application.

One thing I haven't tried is setting the Bing provider in XAML instead of in code behind -- who knows it might solve the issue. One reason is that I'm just not sure how to do that (with OSM it's pretty straightforward, but Bing requires a key and stuff). The second reason is that in our live application we want our client to be able to switch between providers on the fly, so we HAVE to be able to it in code-behind anyway.

I've already created a support ticket for this issue, but I'm posting it here to in case anyone has any ideas.

<UserControl x:Class="TestRadMapBlurriness.MainPage"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
 
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid Name="GridMap" />
        <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="30">
            <Button Name="BtnTimer" Content="Start" Click="BtnTimer_Click" MinWidth="120" />
            <Button Name="BtnProvider" Content="BING" Click="BtnProvider_Click" MinWidth="120"/>
        </StackPanel>
    </Grid>
</UserControl>


public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
 
            // Prepare the timer that will recreate a new MapWrapper every x seconds
            _refreshDataTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 3) };
            _refreshDataTimer.Tick += refreshDataTimer_Tick;
 
            // Label the buttons
            BtnTimer.Content = "Start";
            BtnProvider.Content = "BING";
        }
 
        private DispatcherTimer _refreshDataTimer;
 
        void refreshDataTimer_Tick(object sender, EventArgs e)
        {
            Refresh();
        }
 
        private int _refreshCounter = 0;
 
        private void Refresh()
        {
            // Remove any existing maps
            while (true)
            {
                MapWrapper mapWrapper = GridMap.Children.OfType<MapWrapper>().FirstOrDefault();
                if (mapWrapper == null) break;
                Debug.WriteLine((_refreshCounter).ToString() + ": {0:x16} Removing MapWrapper", mapWrapper.GetHashCode());
                mapWrapper.Dispose();
                GridMap.Children.Remove(mapWrapper);
            }
 
            // Add a new map
            MapWrapper newMapWrapper = new MapWrapper(_providerName);
            GridMap.Children.Add(newMapWrapper);
            Debug.WriteLine((_refreshCounter++).ToString() + ": {0:x16} Added new MapWrapper", newMapWrapper.GetHashCode());
        }
 
        /// <summary>
        /// Start/stop the timer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnTimer_Click(object sender, RoutedEventArgs e)
        {
            if (BtnTimer.Content.ToString() == "Stop")
            {
                _refreshDataTimer.Stop();
                BtnTimer.Content = "Start";
            }
            else
            {
                _refreshDataTimer.Start();
                BtnTimer.Content = "Stop";
            }
        }
 
        private string _providerName = "";
 
        /// <summary>
        /// Change the provider. The next new MapWrapper will be initialized with the new provider.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnProvider_Click(object sender, RoutedEventArgs e)
        {
            if (BtnProvider.Content.ToString() == "BING")
            {
                _providerName = "OpenStreetMapProvider";
                BtnProvider.Content = "OSM";
            }
            else
            {
                _providerName = "";
                BtnProvider.Content = "BING";
            }
        }
    }

<UserControl x:Class="TestRadMapBlurriness.MapWrapper"
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"            
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
     
    <Grid x:Name="LayoutRoot" Background="White">
        <telerik:RadMap x:Name="RadMap1"
                        Center="38.8763793426777, -77.0368488348389"
                        ZoomLevel="14"
                        MiniMapExpanderVisibility="Collapsed"
                        >
            <!--<telerik:RadMap.Providers>-->
                <!--<telerik:OpenStreetMapProvider />-->               
                <!--<telerik:BingMapTrafficProvider />-->               
            <!--</telerik:RadMap.Providers>-->
        </telerik:RadMap>
    </Grid>
</UserControl>

public partial class MapWrapper : UserControl, IDisposable
    {
        private string _providerName = "";
 
        public MapWrapper(string providerName)
        {
            InitializeComponent();
            _providerName = providerName;
            SetProvider();
        }
 
        private const double BaseAerialLayerOpacity = 1.0;
        private const double RoadLayerOpacity = 0.5;
 
        private void SetProvider()
        {
            MapProviderBase provider;
 
            if (_providerName == "OpenStreetMapProvider")
            {
                provider = new OpenStreetMapProvider();
            }
            else
            {
                var bingMapId = ((Microsoft.Maps.MapControl.ApplicationIdCredentialsProvider)App.Current.Resources["AppId"]).ApplicationId;
                BingMapProvider baseAerialProvider = new BingMapProvider(MapMode.Aerial, true, bingMapId);
                provider = baseAerialProvider;
            }
 
            this.RadMap1.Provider = provider;
        }
 
        #region Dispose
 
        private bool _disposed = false;
 
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        protected virtual void Dispose(bool disposing)
        {
            try
            {
                Debug.WriteLine("Dispose(" + disposing.ToString() + ") {0:x16}", this.GetHashCode());
                if (!_disposed)
                {
                    if (disposing)
                    {
                        // Free managed objects
                        //this.RadMap1.Providers.Clear();
                        //this.RadMap1.Provider = null;
                        RadMap1.Dispose();                       
                        Debug.WriteLine("Dispose manually {0:x16}", this.GetHashCode());
                    }
                    else
                    {
                         
                    }                   
 
                    //this.RadMap1.Providers.RemoveAll();
                    //Debug.WriteLine("this.RadMap1.Providers.RemoveAll();");
 
                    _disposed = true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Dispose(" + disposing.ToString() + ") failed: " + ex.Message);
            }
        }
         
        ~MapWrapper()
        {
            Dispose(false);
        }
 
        #endregion






4 Answers, 1 is accepted

Sort by
0
Andrey
Telerik team
answered on 10 Feb 2014, 05:34 PM
Hello Jeroen,

Thank you for the feedback and for the sample code.

We were able to reproduce the problem. This is why I've logged the item in our feedback portal. The fix should be available with the 2014 Q1 release. You can track status of the task here.

Regards,
Andrey Murzov
Telerik

Check out the new Telerik Platform - the only modular platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native apps. Register for the free online keynote and webinar to learn more about the Platform on Wednesday, February 12, 2014 at 11:00 a.m. ET (8:00 a.m. PT).

0
Jeroen
Top achievements
Rank 1
answered on 10 Feb 2014, 05:39 PM
What about the second issue (Bing imagery fails to show)? I'd suspect it might not be directly related to the memory leak, but it's equally problematic.
0
Andrey
Telerik team
answered on 11 Feb 2014, 12:26 PM

Hi Jeroen,

Unfortunately we can't reproduce this issue on our side. But it looks that sometimes the Bing imagery service is initialized wrong. You can handle the BingMapProvider.InitializationFaulted event to check it.

Regards,
Andrey Murzov
Telerik

Check out the new Telerik Platform - the only modular platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native apps. Register for the free online keynote and webinar to learn more about the Platform on Wednesday, February 12, 2014 at 11:00 a.m. ET (8:00 a.m. PT).

0
Jeroen
Top achievements
Rank 1
answered on 11 Feb 2014, 01:20 PM
Thanks. Seemed to have been a problem with Bing instead, which has been sorted out now.
Tags
Map
Asked by
Jeroen
Top achievements
Rank 1
Answers by
Andrey
Telerik team
Jeroen
Top achievements
Rank 1
Share this question
or