BingMapProvider memory leak and exceptions

5 posts, 0 answers
  1. Jeroen
    Jeroen avatar
    49 posts
    Member since:
    Feb 2012

    Posted 07 Feb 2014 Link to this post

    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






  2. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 10 Feb 2014 Link to this post

    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).

  3. DevCraft banner
  4. Jeroen
    Jeroen avatar
    49 posts
    Member since:
    Feb 2012

    Posted 10 Feb 2014 in reply to Andrey Link to this post

    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.
  5. Andrey
    Admin
    Andrey avatar
    1681 posts

    Posted 11 Feb 2014 Link to this post

    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).

  6. Jeroen
    Jeroen avatar
    49 posts
    Member since:
    Feb 2012

    Posted 11 Feb 2014 in reply to Andrey Link to this post

    Thanks. Seemed to have been a problem with Bing instead, which has been sorted out now.
Back to Top
DevCraft banner