English 中文(简体)
How do you make sure WPF releases large BitmapSource from Memory?
原标题:

System: Windows XP SP3, .NET 3.5, 4GB RAM, Dual 1.6gHz

I have a WPF application that loads and transitions (using Storyboard animations) extremely large PNGs. These PNGs are 8190x1080 in resolution. As the application runs it appears to cache the images and the system Memory slowly creeps up. Eventually it chokes the system and throws the OutOfMemoryException.

Here are the steps I am currently taking to try to solve this:

1)I am removing the BitmapSource objects from the app

2)I am setting the BitmapSource BitmapCacheOption to None when I load the BitmapSource

3)I am Freezing the BitmapSource once it s loaded.

4)I am deleting all references to the Image that uses the source as well as any references to the source itself.

5)Manually calling GC.Collect() after above steps have completed.

Hoping to figure out why WPF is hanging onto memory for these images and a possible solution to ensure that the memory used to load them is properly recovered.

最佳回答

You certainly have put in a lot of work on this. I think the main problem is that BitmapCacheOption.None doesn t prevent the underlying BitmapDecoder(s) from being cached.

There are several tricky solutions to this such as doing a GC.Collect(), loading 300 small images from 300 different Uris, and calling GC.Collect() again, but the simple one is straightforward:

Instead of loading from a Uri, just construct a Stream and pass it to BitmapFrame s constructor:

var source = new BitmapImage();
using(Stream stream = ...)
{
  source.BeginInit();
  source.StreamSource = stream;
  source.CacheOption = BitmapCacheOption.OnLoad;    // not a mistake - see below
  source.EndInit();
}

The reason this should work is that loading from a stream completely disables the cache. Not only is the top-level source not cached, but none of the internal decoders are cached either.

Why BitmapCacheOption.OnLoad? It seems counterintuitive, but this flag has two effects: It enables caching if caching is possible, and it causes the load to happen at EndInit(). In our case caching is impossible, so all it does it cause the load to happen immediately.

Obviously you ll want to run this code off your UI thread, then freeze the BitmapSource so you can move it over.

You may also wonder why I didn t use BitmapCreateOptions.IgnoreImageCache. Other than the fact that caching is impossible any with no URI given, the IgnoreImageCache doesn t completely ignore the image cache: It only ignores it for reading. So even if IgnoreImageCache is set, the loaded image is still inserted into the cache. The difference is that the existing image in the cache is ignored.

问题回答

暂无回答




相关问题
WPF convert 2d mouse click into 3d space

I have several geometry meshes in my Viewport3D, these have bounds of (w:1800, h:500, d:25). When a user clicks in the middle of the mesh, I want the Point3D of (900, 500, 25)... How can I achieve ...

Editing a xaml icons or images

Is it possible to edit a xaml icons or images in the expression design or using other tools? Is it possible to import a xaml images (that e.g you have exported) in the expression designer for editing?...

WPF: writing smoke tests using ViewModels

I am considering to write smoke tests for our WPF application. The question that I am faced is: should we use UI automation( or some other technology that creates a UI script), or is it good enough to ...

WPF - MVVM - NHibernate Validation

Im facing a bit of an issue when trying to validate a decimal property on domain object which is bound to a textbox on the view through the viewmodel. I am using NHibernate to decorate my property on ...

How do WPF Markup Extensions raise compile errors?

Certain markup extensions raise compile errors. For example StaticExtension (x:Static) raises a compile error if the referenced class cannot be found. Anyone know the mechanism for this? Is it baked ...

WPF design-time context menu

I am trying to create a custom wpf control, I m wondering how I can add some design-time features. I ve googled and can t seem to get to my goal. So here s my simple question, how can I add an entry ...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签