Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

freeze wpf app during update binding source

I created thumbnails based on ListView control. On ListView.ItemSource I bind ObservableColletion<Photos> Photos{get;set}.

I create thumbnail images in another threads also in parallel way.

I simplified my code.

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;
    }
}

Problem is here:

//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;

When I reenable binding UI freeze, I tried use dispatcher but result is same UI freeze.

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

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

How can I avoid freeze UI?

EDITED:

I edited my code based on Dean K. advice. I dont break bind before update source of listview.

I updated source of ListView.ItemSource via Dispatcher:

Sync Invoke:

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

            }), DispatcherPriority.ContextIdle);

Result - UI behavior.

Images are being added continuously but if collection contains more than 500 images at the and WPF window freezes. For example it is not possible move window, scroll listview.

Async Invoke

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

            }), DispatcherPriority.ContextIdle);

Result - UI behavior.

At start app freezes but after several seconds images are being added continously and also is it possible move window, scroll listview.

So my question is what is root of problem that app freezes ? How can I avoid this behaviour. I upload sample application.

like image 422
imodin Avatar asked Jun 24 '26 20:06

imodin


1 Answers

Don't break the binding before adding items to the ObservableCollection.

Bind Thumbnails.ItemsSource to Photos OC and than on another thread load and add items to Photos OC. That way your UI will not freeze.

You might want to use the multithreaded ObservableColleciton you can find on code project. Search for ObservableCollectionMt...

like image 64
Dean Kuga Avatar answered Jun 30 '26 10:06

Dean Kuga



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!