如何在WPF应用程序中处理图像内存?

时间:2015-08-07 14:25:00

标签: c# wpf

我在WPF中有一个非常图像密集型的应用程序。我尽可能以最好的方式管理记忆,但图像正在推动我超出预算。它们只是在某个点停止渲染,然后应用程序崩溃。我将图像控件的源绑定到给定路径。

<Image Source="{Binding ImagePath, Mode=OneWay}"/>

有没有更好的方法来解决这个问题?也许我可以关闭缓存?我知道问题出在图像上,因为当我停止显示图像时,问题就会消失。

1 个答案:

答案 0 :(得分:0)

我认为我的问题是图像被不必要地重新创建。我不知道怎么做。我不知道为什么。当我创建自己的缓存服务并使用BitmapImage而不是路径时,内存问题就消失了。我甚至可以看到它被包含在转换器中,该转换器采用路径并生成缓存的BitmapImage。这不太理想。它只能摆脱重复。我仍然需要玩到期,但我很高兴这是一个解决方案。

public class ImageCachingSystem : IImageCachingSystem
{
    private readonly DispatcherTimer _timer = new DispatcherTimer();

    private readonly object l_cachesByName = new object();
    private readonly Dictionary<String, ImageCache> _cachesByName = new Dictionary<String, ImageCache>();

    public ImageCachingSystem()
    {
        _timer.Interval = TimeSpan.FromSeconds(10);
        _timer.Tick += OnTick;
        _timer.Start();
    }

    public BitmapImage GetImage(String a_path)
    {
        return GetImage(new Uri(a_path));
    }

    public BitmapImage GetImage(Uri a_url)
    {
        lock (l_cachesByName)
        {
            var path = a_url.ToString().ToLower();

            if (_cachesByName.ContainsKey(path))
            {
                return _cachesByName[path].Image;
            }
            else
            {
                var image = new BitmapImage(a_url);
                image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                image.Freeze();

                _cachesByName[path] = new ImageCache
                {
                    Expiration = DateTime.Now + TimeSpan.FromMinutes(30),
                    Path = path,
                    Image = image,
                };

                return image;
            }
        }
    }

    private void OnTick(object sender, EventArgs e)
    {
        lock (l_cachesByName)
        {
            var expired = _cachesByName.Where(i => i.Value.Expiration < DateTime.Now).Select(i => i.Key);

            foreach (var key in expired.ToArray())
                _cachesByName.Remove(key);
        }
    }


    class ImageCache
    {
        public String Path { get; set; }
        public DateTime Expiration { get; set; }
        public BitmapImage Image { get; set; }
    }
}