Enough to call Children.Clear on a WPF canvas to get rid of old controls before adding new ones?

Lasse V. Karlsen picture Lasse V. Karlsen · Feb 18, 2010 · Viewed 9.7k times · Source

I am experimenting with WPF and re-implementing my old maze screensaver.

My code basically adds a bunch of images to the canvas, building up a grid, 64x64 pixel images side by side, to cover the entire canvas. Then I "animate" movement in the maze, which is supposed to scroll the maze around, by adjusting a translate transformation, and swapping out the images.

However, it seems I have a leak of some sort. Whenever I resize the window, I want to re-build the image components in order to cover the form again, either with more or fewer images.

If I drag the lower left corner of the form around in tight circles the rebuild part gets slower and slower.

To remove the old controls I simply did this:

_Canvas.Children.Clear();

is this enough? Due to the slowdown I assume it isn't.

However, since the maze is currently not "discovered" by the "avatar", the maze images are drawn with 25% opacity, and I would assume that if I failed to remove them, I would get many images on top of each other, but it doesn't appear to be that either.

I am caching the image sources, the image components are created like this:

_Images = new Image[(int)width, (int)height];
for (int x = -1; x < width - 1; x++)
{
    for (int y = -1; y < height - 1; y++)
    {
        Image i = new Image();
        i.Width = 64;
        i.Height = 64;
        i.Source = _Outside;
        Canvas.SetLeft(i, x * 64);
        Canvas.SetTop(i, y * 64);
        _Canvas.Children.Add(i);
        _Images[x + 1, y + 1] = i;
    }
}

Afterwards they're assigned images to show like this:

Maze.Square sq = _Maze[_TopLeftMazeX + x, _TopLeftMazeY + y];
Image img = _Images[x + 1, y + 1];

if (sq.Seen)
    img.Opacity = 1.0;
else
    img.Opacity = 0.25;
switch (sq.Type)
{
    case Maze.SquareType.Hallway:
        img.Source = _Hallway;
        break;

    case Maze.SquareType.Wall:
        img.Source = _Wall;
        break;

    case Maze.SquareType.Outside:
        img.Source = _Outside;
        break;
}

What else should I look for? Is there a need to dispose of the image components in any way?

Answer

Jake picture Jake · Feb 18, 2010

Calling _Canvas.Children.Clear(); will remove all references to the images from the visual tree, so there are no leaks there. You may want to check for old image references being held in _Images, or some other collection you might be maintaining. For instance, you said that you were caching the image sources - doing this inefficiently, or maintaining an ever-growing list of stale images will definitely impact your system.