更新绑定源时WPF应用程序会冻结

3

我基于ListView控件创建了缩略图。在 ListView.ItemSource 上,我绑定了 ObservableColletion<Photos> Photos{get;set}

我还以并行方式在另一个线程中创建缩略图图像。

我简化了我的代码。

public class ThumbnailCreator
{
    public static List<Photos> CreateThumbnailImage(List<Photos> photos)
    {
        var thumbnails = new List<Photos>();

        Parallel.ForEach(photos, photo =>
        {
            var bitmap = new BitmapImage();

            bitmap.BeginInit();

            bitmap.DecodePixelHeight = 128;

            bitmap.DecodePixelWidth = 128;

            bitmap.CacheOption = BitmapCacheOption.OnLoad;

            bitmap.CreateOptions = BitmapCreateOptions.DelayCreation;

            bitmap.UriSource = new Uri(photo.FullPath);

            bitmap.EndInit();

            if (bitmap.CanFreeze)
                bitmap.Freeze();

           thumbnails.Add(new Photos{ThumbnailImage = bitmap}); 

        });

        return thumbnails;
    }
}

问题在这里:
//I break binding before I start refreshing thumbnails
          this.Thumbnails.ItemsSource = null;

//load files from folder
          List<Photos> photos = _fileManager.LoadFromDir(folderBrowserDialog.SelectedPath);

//create thumbnail images in another threads, not on UI
          List<Photos> thumbnails = ThumbnailCreator.CreateThumbnailImage(photos);

//create new source
          Photos = new ObservableCollection<Photos>(thumbnails);

//reenable binding, this part of code cause that UI free
          this.Thumbnails.ItemsSource = Photos;

当我重新启用绑定UI冻结时,我尝试使用Dispatcher,但结果仍然是UI冻结。

                this.Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() =>
                {
                    Photos = new ObservableCollection<Photos>(thumbnails);

                    this.Thumbnails.ItemsSource = Photos;
                }));

我该如何避免UI冻结?

编辑:

根据Dean K.的建议,我修改了代码。在更新列表视图的数据源之前,我不会断开绑定。

我通过Dispatcher更新了ListView.ItemSource的数据源:

同步调用:

            App.Current.Dispatcher.Invoke(new Action(() =>
            {
                thumbnails.Add(new Photos { ThumbnailImage = bitmap });

            }), DispatcherPriority.ContextIdle);

结果 - 用户界面的行为。

图片正在不断地添加,但是如果集合包含超过500张图片,则WPF窗口最终会冻结。例如,无法移动窗口或滚动listview。

异步调用

            App.Current.Dispatcher.InvokeAsync(new Action(() =>
            {
                thumbnails.Add(new Photos { ThumbnailImage = bitmap });

            }), DispatcherPriority.ContextIdle);

结果 - 用户界面行为。

启动应用程序时会出现冻结现象,但几秒钟后会不断添加图像,同时也可以移动窗口、滚动列表视图。

我的问题是应用程序冻结的根源是什么?如何避免这种行为?我上传了一个示例应用程序

1个回答

1

在向 ObservableCollection 添加项目之前不要打破绑定。

Thumbnails.ItemsSource 绑定到 Photos OC,然后在另一个线程上加载并添加项目到 Photos OC。这样您的 UI 就不会冻结。

您可能想使用在代码项目中找到的多线程 ObservableColleciton。搜索 ObservableCollectionMt...


我根据您的建议编辑了我的示例,但应用程序仍然冻结。更多细节请参见我的原始问题。 - imodin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接