Click here to Skip to main content
15,886,038 members
Home / Discussions / WPF
   

WPF

 
AnswerRe: Question about NotifyCollectionChangedEventArgs Pin
Richard Deeming1-Mar-22 21:42
mveRichard Deeming1-Mar-22 21:42 
QuestionAnimation on DataGridRow jumps to wrong row when scrolling Pin
Mc_Topaz27-Feb-22 23:31
Mc_Topaz27-Feb-22 23:31 
AnswerRe: Animation on DataGridRow jumps to wrong row when scrolling Pin
Gerry Schmitz28-Feb-22 8:11
mveGerry Schmitz28-Feb-22 8:11 
GeneralRe: Animation on DataGridRow jumps to wrong row when scrolling Pin
Mc_Topaz28-Feb-22 20:28
Mc_Topaz28-Feb-22 20:28 
QuestionLabelprint on Thermotransfer Pin
Member 118002289-Feb-22 0:34
Member 118002289-Feb-22 0:34 
QuestionRe: Labelprint on Thermotransfer Pin
Eddy Vluggen9-Feb-22 3:13
professionalEddy Vluggen9-Feb-22 3:13 
QuestionWPF c# onStartUp() view model problem with multiple data inputs Pin
StealthRT5-Feb-22 7:31
StealthRT5-Feb-22 7:31 
AnswerRe: WPF c# onStartUp() view model problem with multiple data inputs Pin
Gerry Schmitz5-Feb-22 18:16
mveGerry Schmitz5-Feb-22 18:16 
AnswerRe: WPF c# onStartUp() view model problem with multiple data inputs Pin
Kevin Marois21-Feb-22 11:29
professionalKevin Marois21-Feb-22 11:29 
QuestionWpf System.Windows.Media.ImageSourcesConverter cannot be applied Pin
StealthRT1-Feb-22 16:08
StealthRT1-Feb-22 16:08 
AnswerRe: Wpf System.Windows.Media.ImageSourcesConverter cannot be applied Pin
Richard Deeming1-Feb-22 21:49
mveRichard Deeming1-Feb-22 21:49 
GeneralRe: Wpf System.Windows.Media.ImageSourcesConverter cannot be applied Pin
StealthRT2-Feb-22 2:39
StealthRT2-Feb-22 2:39 
GeneralRe: Wpf System.Windows.Media.ImageSourcesConverter cannot be applied Pin
Richard Deeming2-Feb-22 2:44
mveRichard Deeming2-Feb-22 2:44 
Question(beginner) There must be a better way (TextBlock properties) Pin
Maximilien26-Jan-22 5:08
Maximilien26-Jan-22 5:08 
AnswerRe: (beginner) There must be a better way (TextBlock properties) Pin
Richard Deeming26-Jan-22 5:33
mveRichard Deeming26-Jan-22 5:33 
GeneralRe: (beginner) There must be a better way (TextBlock properties) Pin
Maximilien26-Jan-22 9:10
Maximilien26-Jan-22 9:10 
QuestionConverting a byte[] to a ImageSource means huge memory leak Pin
Starwer24-Jan-22 11:42
Starwer24-Jan-22 11:42 
AnswerRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Gerry Schmitz24-Jan-22 16:15
mveGerry Schmitz24-Jan-22 16:15 
GeneralRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Starwer24-Jan-22 19:58
Starwer24-Jan-22 19:58 
GeneralRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Gerry Schmitz24-Jan-22 21:26
mveGerry Schmitz24-Jan-22 21:26 
GeneralRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Starwer25-Jan-22 7:56
Starwer25-Jan-22 7:56 
AnswerRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Richard Deeming25-Jan-22 21:51
mveRichard Deeming25-Jan-22 21:51 
GeneralRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Starwer26-Jan-22 9:10
Starwer26-Jan-22 9:10 
Hi Richard,

Thanks a lot for this very complete answer.

I've removed the finalizer and implemented the IDisposable as you suggested. I like the DisposableObservableCollection proposal. It looks very neat this way.

Unfortunatly this doesn't solve the problem. The leak is just as bad as before, with Image/BitmapImage and MemoryStream never being freed. It has probabably something to do with the fact that the MemoryStream.Dispose() doesn't do anything like explain on this page.

In the end the code looked like this:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Toy
{


	internal class ToyItem : INotifyPropertyChanged, IDisposable
    {
        #region Boilerplate INotifyPropertyChanged

        protected void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, e);
        }

        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler? PropertyChanged;

        #endregion

        public void Dispose()
        {
            if (Data is BitmapImage image)
            {
                image.StreamSource.Dispose();
            }

            Data = null;
        }

        /// <summary>
		/// Build an image from Picture bytes
		/// </summary>
		/// <param name="imageData">Picture as array of bytes</param>
		/// <returns>Pictures as BitmapImage</returns>
		public static ImageSource? BitmapFromRaw(byte[]? imageData)
		{
			if (imageData == null) return null;
			var image = new BitmapImage();
            var mem = new MemoryStream(imageData, false);
			//mem.Position = 0;
			image.BeginInit();
			//image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
			//image.CacheOption = BitmapCacheOption.None;
			//image.UriSource = null;
			image.StreamSource = mem;
			image.EndInit();
            //mem.Close();
            //mem.Dispose();
            image.Freeze();
 
            return image;
		}

		public ImageSource? Data
        {
            get { return _Data; }
            set
            {
                if (value != _Data)
                {
                    _Data = value;
                    OnPropertyChanged();
                }
            }
        }
        private ImageSource? _Data;
        
        public ToyItem ()
        {
            Data = BitmapFromRaw(Properties.Resources.pexels_jonathan_faria_8581946);
            //Data = new BitmapImage(new Uri(@"E:\Downloads\pexels-jonathan-faria-8581946.jpg"));
        }

    }


    public class DisposableObservableCollection<T> : ObservableCollection<T>, IDisposable
    where T : IDisposable
    {
        public DisposableObservableCollection(List<T> list) : base(list)
        {
        }

        public DisposableObservableCollection(IEnumerable<T> collection) : base(collection)
        {
        }

        public DisposableObservableCollection() : base ()
        {
        }

        protected override void SetItem(int index, T item)
        {
            T oldItem = this[index];
            base.SetItem(index, item);
            oldItem?.Dispose();
        }

        protected override void RemoveItem(int index)
        {
            T item = this[index];
            base.RemoveItem(index);
            item?.Dispose();
        }

        protected override void ClearItems()
        {
            List<T> itemsToDispose = Items.Where(i => i != null).ToList();
            base.ClearItems();
            foreach (T item in itemsToDispose)
            {
                item.Dispose();
            }
        }


        public void Dispose()
        {
            ClearItems();
        }

    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        DisposableObservableCollection<ToyItem> ToyList = new DisposableObservableCollection<ToyItem>();

        int Counter = 0;

        public MainWindow()
        {
            InitializeComponent();

            wxToy.DataContext = ToyList;
            wxButton.Content = Counter;
        }

        private void gcButton_Click(object sender, RoutedEventArgs e)
        {
            GC.Collect();
        }

        private void wxButton_Click(object sender, RoutedEventArgs e)
        {
            wxButton.Content = ++Counter;

            //foreach (var item in ToyList)
            //{
            //    item.Data = null;
            //}

            ToyList.Clear();

            for (int i = 0; i < 5; i++)
            {
                ToyList.Add(new ToyItem());
            }
        }
    }

}

GeneralRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Gerry Schmitz27-Jan-22 6:33
mveGerry Schmitz27-Jan-22 6:33 
GeneralRe: Converting a byte[] to a ImageSource means huge memory leak Pin
Starwer27-Jan-22 20:29
Starwer27-Jan-22 20:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.