1

I have a huge memory use progress when loading a tif frames into dynamically created Image controls, that's logic, But that used memory dosen't unload when I remove my Image controls ! and that's what I don't understand. here is my test code: XAML:

<Grid>
    <Button Content="Load" Margin="0,0,582,280" Click="OnLoadClck"/>
    <ScrollViewer Margin="10,54,0,0" HorizontalScrollBarVisibility="Visible">
        <StackPanel Orientation="Horizontal" x:Name="panel">

        </StackPanel>
    </ScrollViewer>
    <Button Content="Unload" Margin="147,0,435,280" Click="OnUnloadClick"/>
</Grid>

Code behinde:

private void OnLoadClck(object sender, RoutedEventArgs e)
{
    TiffBitmapDecoder tbd = new TiffBitmapDecoder(new Uri("d:\\test.tif"), BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnDemand);
    for (int i = 0; i < tbd.Frames.Count; i++)
    {
        var f = tbd.Frames[i];

        Image img = new Image{Width=100, Height=150 };
        img.Source = f;

        panel.Children.Add(img);
    }

}

private void OnUnloadClick(object sender, RoutedEventArgs e)
{
    while(panel.Children.Count>0)
    {
        Image img = panel.Children[0] as Image;
        img.Source = null;
        panel.Children.Remove(img);
    }
}

I believe my control unloading task is going bad but I don't know how to do it in the right way. Thank you for your help.

hsnslh
  • 55
  • 8
  • Consider using an ItemsControl with a horizontal StackPanel as ItemsPanel. Bind its ItemsSource property to an `ObservableCollection` containing the BitmapFrames. Create an ItemTemplate with ``. – Clemens Mar 14 '17 at 11:28
  • This is just a test app – hsnslh Mar 14 '17 at 11:33
  • Try to create the TiffBitmapDecoder from a FileStream (instead of an Uri) with `BitmapCreateOptions.None` and `BitmapCacheOption.OnLoad`. Dispose of the stream right after retrieving the Frames collection. – Clemens Mar 14 '17 at 11:36
  • 1
    Additionally to the Clemens suggestion, you should also call Freeze() method on your BitmapFrame objects. Using unfrosen freezable objects can also lead to memory leaks in some cases. – Pavel Mar 14 '17 at 12:16
  • @Pavel Good point, but the BitmapFrame instances in the Frames collection are most certainly already frozen when loaded from a FileStream with BitmapCacheOption.OnLoad. – Clemens Mar 14 '17 at 12:30

1 Answers1

0

I've checked your sample application and I don't see any memory leak there. I've used 24bit lzw compressed tiff image from here. Objects are released after Garbage Collection as expected. I've added a third button forsing the GarbageCollection to occur immideatly: GC.Collect();

And here is the result: http://www.screencast.com/t/F5hhyTkAQ3e

When you add images they are added to the memory. When you click unload you remove any reference to them, but that doesn't mean that Garbage Collection will start immediatly. Objects are put in Large Objects Heap and Garbage Collection there is not happening as fast as for First Generation objects. But when GC is done(for example, you can click add after unload, that might forse GC), the objects are successfully removed from memory.

3615
  • 3,787
  • 3
  • 20
  • 35
  • indeed, the GC.Collect() does some improvements. – hsnslh Mar 14 '17 at 13:10
  • how if I don't want to remove my imaage controls ? I want to just unload the sources – hsnslh Mar 14 '17 at 13:11
  • You should **never call GC.Collect** in your production code. I've put it there just to demonstrate you that there is no memory leak. Forcing GC can significantly degrade performance. All you have to do is to ensure, that there are no objects, that holds references to your images. – 3615 Mar 14 '17 at 13:14
  • Not sure what do you mean but not removing image controls? You wan't to continue displaying images, but not have them loaded in memory? Well, that's impossible, to have them displayed on the screen they must be loaded into the memory. – 3615 Mar 14 '17 at 13:16
  • My goal is to simulate a thumbnail viewer of tiff files So I want to unload images that are not visible to the user – hsnslh Mar 14 '17 at 13:22
  • Well, that's fine, just unload them, when you are hiding them, like you shown in the example. It should not have memory leaks. – 3615 Mar 14 '17 at 13:42