【问题标题】:Image loading in multithreading manner多线程方式加载图片
【发布时间】:2016-08-30 12:03:42
【问题描述】:

当我尝试在导致内存泄漏(大量 HWNd 指针)的独立线程中加载图像源时(ImgSource1 是 VM 上的可绑定属性)

Thread task = new Thread(() =>
        {
            try
            {
                ImageSource newSource = CreateImageSource(imageList[CurrentSourceIndex], true);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    ImgSource1 = newSource; // <==  Memory leak is here
                });

                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            catch(Exception ex)
            {
                LogService.WriteLog(ex);
            }
            IsImageChangeAccessible = true;

        });
        task.IsBackground = true;
        task.Start();

如果我使用此代码会导致内存泄漏并且 wpf 在加载了大约 20-30k 图像后停止绘制图像。基于 Dispatcher 存储的 Window 指针的内存泄漏。这里有一些来自内存分析器的图像: 调用树: 和内存图,在最大对象图的最后一点泄漏的对象(HwndSubclass):

但是当我在没有Thread 的情况下使用相同的代码时,一切正常......(尚未在长期测试中测试想法)。

那么如何以多线程方式从文件中加载图像源而不会出现这种内存泄漏?

图片加载代码:

var src = new BitmapImage();
                src.BeginInit();
                src.UriSource = new Uri(file, UriKind.Absolute);
                src.CacheOption = BitmapCacheOption.OnLoad;
                src.EndInit();
                src.Freeze();
                return src;

【问题讨论】:

  • 您使用的是哪个 .NET 版本?
  • 您还没有展示CreateImageSource 中发生了什么以及imageList 是什么。
  • 可能你正在分配一些你应该调用 dispose() 但不是的图像资源
  • @Sam .Net 4.6 @Clemens CreateImageSource() 在帖子末尾列出,imageList 只是一个文件名列表。

标签: c# wpf multithreading image memory-leaks


【解决方案1】:

如果您有可能绑定Image 控件的Source 属性并设置IsAsync=True,wpf 将关心自己在后台线程中获取图像。

一般来说,如果控件定义了名称(或 x:Name),wpf 会将控件保留在内存中,因此您应该注意这一点。

【讨论】:

  • 感谢您的帮助。今晚刚刚测试,目前效果很好,将长期测试。
猜你喜欢
  • 1970-01-01
  • 2012-11-28
  • 2021-02-21
  • 1970-01-01
  • 2011-09-02
  • 2012-05-17
  • 2017-07-05
  • 1970-01-01
  • 2020-08-09
相关资源
最近更新 更多