Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

In my application I have isues with unfreed memory. After several tries I broke down the problem to a simplified WPF project. It opens a simple System.Windows.Window with a Button, which starts the MapWindow listed below. The MapWindow has only an AxMapControl which loads a sample map, an AxTocControl and an AxToolbarControl both buddys of the MapControl.

I simply test the memory usage by looking at the task manager. When I hit the start button the first time the MapWindow opens and the memory usage is (depending on the project file and the size of MapControl) let's say 100 MB. Close the MapWindow and the memory goes down to ca. 65 MB. Hit the start button again (~100 MB) and close the window (~65 MB). This works fine for every iteration.

Now uncomment the line

toolbarControl.AddItem("esriControls.ControlsSelectTool");

and repeat the test. Hit the start button (~105 MB), close (~70 MB) and start (~115 MB), close (~80 MB), start (~125 MB) and close (~90 MB) and so on.

As you can see, the memory usage adds ~10 MB per start/close. The actual amount depends on the project and (!) on the size of the MapControl (even if no layer is activated in TOC on start up). So I asume, that there is some kind of bitmap cached and not freed correctly.

Can anyone reproduce this behavior? Is there a way to manually free this ControlsSelectTool? Or is this a bug that needs to be reported to Esri?

Here comes the code for the MapWindow:

using System;
using System.Windows;
using ESRI.ArcGIS.Controls;
using System.Runtime.InteropServices;

namespace ArcEngineTest
{
  public partial class MapWindow : Window
  {
    AxMapControl _mapControl;
    AxToolbarControl _toolbarControl;
    AxTOCControl _tocControl;

    public MapWindow()
    {
      InitializeComponent();

      _mapControl = new AxMapControl();
      mapHost.Child = _mapControl;

      _toolbarControl = new AxToolbarControl();
      toolbarHost.Child = _toolbarControl;

      _tocControl = new AxTOCControl();
      tocHost.Child = _tocControl;

      Loaded += new RoutedEventHandler(LoadMap);    
    }

    private void LoadMap(object sender, RoutedEventArgs e)
    {
      _tocControl.SetBuddyControl(_mapControl);
      _toolbarControl.SetBuddyControl(_mapControl);

      //_toolbarControl.AddItem("esriControls.ControlsSelectTool"); // uncomment this line to cause memory leak; only happens with this specific esriControl ControlsSelectTool

      _mapControl.LoadMxFile(@"Z:\project.mxd");
      _mapControl.Refresh();
    }

    protected override void OnClosed(EventArgs e)
    {
      try
      {
        // Free memory

        mapHost.Child = null;
        toolbarHost.Child = null;
        tocHost.Child = null;

        _tocControl.SetBuddyControl(null);
        _tocControl.Dispose();
        _tocControl = null;

        for (int i = 0; i < _toolbarControl.Count; i++)
        {
          ReleaseComObject(_toolbarControl.GetItem(i));
        }
        _toolbarControl.SetBuddyControl(null); // necessary
        _toolbarControl.RemoveAll();
        _toolbarControl.Dispose();
        _toolbarControl = null;

        _mapControl.Dispose();
        _mapControl = null;

        toolbarHost.Dispose();
        mapHost.Dispose();
        tocHost.Dispose();

        ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown();

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace, "Error on Close");
      }
      base.OnClosed(e);
    }

    public static void ReleaseComObject(object obj)
    {
      if (obj != null)
      {
        int refsLeft = 0;
        do
        {
          refsLeft = Marshal.ReleaseComObject(obj);
        }
        while (refsLeft > 0);
      }
    }
  }
}

The correspondening xaml file is pretty simple:

<Window x:Class="ArcEngineTest.MapWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        WindowState="Maximized">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="30"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="170"/>
      <ColumnDefinition Width="3"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <WindowsFormsHost Grid.Row="0" Grid.ColumnSpan="3" Name="toolbarHost" Height="30"/>

    <WindowsFormsHost Grid.Row="1" Name="tocHost" />
    <GridSplitter Grid.Row="1" Grid.Column="1" Width="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeDirection="Columns" />
    <WindowsFormsHost Grid.Row="1" Grid.Column="2" Name="mapHost" />

  </Grid>
</Window>

Update:

I could provide the test project (Visual Studio 2010 SP1). If anyone is interested, please comment.

share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.