在更新绑定源期间冻结wpf应用程序

时间:2013-11-16 22:18:26

标签: wpf listview binding freeze

我基于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冻结时,我尝试使用调度程序,但结果是相同的UI冻结。

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

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

如何避免冻结用户界面?

编辑:

我根据Dean K.的建议编辑了我的代码。在更新listview的源代码之前我不会破坏绑定。

我通过Dispatcher更新了ListView.ItemSource的源代码:

同步发票:

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

            }), DispatcherPriority.ContextIdle);

结果 - 用户界面行为。

正在连续添加图像,但如果集合中包含超过500个图像,则WPF窗口会冻结。例如,无法移动窗口,滚动列表视图。

异步调用

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

            }), DispatcherPriority.ContextIdle);

结果 - 用户界面行为。

在开始应用程序冻结但几秒钟后连续添加图像,也可以移动窗口,滚动列表视图。

所以我的问题是应用冻结的问题根源是什么?我怎样才能避免这种行为。 I upload sample application

1 个答案:

答案 0 :(得分:1)

在将项目添加到ObservableCollection之前,请勿破坏绑定。

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

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