2

I'm having an issue here :(
I'm trying to write a small game by XAML , kind of repeat-turn game. I used a Storyboard to display elapsed time of turns (usually from 3-6 seconds) by moving a Pointer on a Image (processbar.png) and a Stackpanel (spImageList) where I manipulated and removed a number of BitmapImage on each turn . The code look like this:

<Grid Grid.Column="1">
            <Canvas Canvas.ZIndex="1" >
                <Canvas.Resources>
                    <Storyboard x:Name="myStoryboard" Completed="myStoryboard_Completed">
                        <!-- Animate the center point of the ellipse. -->
                        <DoubleAnimation Storyboard.TargetName="Pointer"
                                     Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
                                     Duration="0:0:7"                                          
                                     From="15" To="310"/>
                    </Storyboard>
                </Canvas.Resources>
                <Image Source="/Assets/Image/pointer.png" x:Name="Pointer">
                    <Image.RenderTransform>
                        <CompositeTransform TranslateX="15"/>
                    </Image.RenderTransform>
                </Image>
            </Canvas>
            <Image Source="/Assets/Image/processbar.png" Width="350"/>
        </Grid>

<Grid Grid.Row="2" HorizontalAlignment="Center" Margin="0,10,0,0">
        <StackPanel x:Name="spImageList" Orientation="Horizontal" HorizontalAlignment="Center" Canvas.ZIndex="1"  />
        <Image Source="/Assets/Image/background.png" Width="550"/>
    </Grid>

c# code

private void myStoryboard_Completed(object sender, EventArgs e)
    {
        spImageList.Children.Clear();      // remove all image from last turn          
        myStoryboard.Begin();

        // Manipulated Images for new turn;   
        ...      
        //

        foreach (var img in ImageList)
            spImageList.Children.Add(img);
    }

When the game finished, I used this code when people left Page:

protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        myStoryboard.Stop();
        spImageList.Children.Clear();          
        base.OnNavigatedFrom(e);
        Debug.WriteLine("mem navigate from Playpage: " + GC.GetTotalMemory(true).ToString());
    }  

But after I played 2 or 3 games, app came slowly and laggy, finally crash my app. I used Debug.writeline and saw that memory app didn't decrease even at MainPage (after navigated from PlayPage) I cleared navigation cache and use GC collect.

if (this.NavigationService.CanGoBack)
        {
            while (this.NavigationService.BackStack.Any())
            {
                this.NavigationService.RemoveBackEntry();
            }
        }
GC.Collect();

So i just wonder if is there a right way to avoid memory leak here ( i think it because of the story board and Images I manipulated in game)

user3448806
  • 897
  • 10
  • 22

1 Answers1

0

There's a leak related to the image class.

Make sure to do this before losing the reference to an image:

BitmapImage bitmapImage = image.Source as BitmapImage;
bitmapImage.UriSource = null;
image.Source = null;

Some more explanation is found here, and here, and there: Why do I get an OutOfMemoryException when I have images in my ListBox?

Community
  • 1
  • 1
Peter
  • 5,608
  • 1
  • 24
  • 43
  • So the line: spImageList.Children.Clear(); didn't clear the images ? Thats weird :) and how about the storyboard, did it expose itself or I have to do something with it ? – user3448806 Sep 06 '14 at 18:04
  • 1
    "Thats weird" Yes, it is :) Think of Image as being `IDisposable`, without a way to call `Dispose` - you need to use the code snippet above to "dispose" an image. It's a known flaw/bug in the framework. The images can cause a memory leak, but I can't guarantee that's the only leak. – Peter Sep 06 '14 at 23:01