Skip to content

Use binding in transform cause memory leak in VS 2022 #6806

@yll690

Description

@yll690
  • .NET Core Version: 6.0, 4.5
  • Windows version: 19044.1826
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes in 4.5.
  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? Yes, only in VS2022.

Problem description:
I have a DataTemplate which contains a RotateTransform whose Angle is bound to the model. When I add models to a ItemsControl and then remove them, the memory usage won't fall to initial value and the object count will increase.

Actual behavior:
As the sample code below, when the button is clicked, 10,000 models will be added to the window and then be removed. But the memory usage and object count remains. Most of the objects are WeakReference, ConditionalWeakTable<Object, Object>, ConditionalWeakTable+Container<Object, Object>, WeakEventManager+ListenerList<EventArgs>.

Timeline memory object count
initial 61M 34196
clicked 133M 155440

Expected behavior:
If I delete the transform or delete the binding, the memory usage and object count will decrease.

Timeline memory object count
initial 62M 34227
clicked 107M 34461

Minimal repro:
MainWindow.xaml

<Window x:Class="WPFTransformBindingMemoryLeak.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFTransformBindingMemoryLeak"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Shape}">
            <Border Background="SandyBrown">
                <Border.RenderTransform>
                    <RotateTransform Angle="{Binding Angle}"/>
                </Border.RenderTransform>
                <TextBlock Text="The Shape"/>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Button Content="start" Name="startB" Click="startB_Click" Width="100" Height="100"/>
        <ItemsControl x:Name="container"/>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace WPFTransformBindingMemoryLeak
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void startB_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                List<Shape> packages = new List<Shape>();
                for (int j = 0; j < 100; j++)
                    packages.Add(new Shape());
                Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, new Action(() =>
                {
                    for (int j = 0; j < 100; j++)
                        container.Items.Add(packages[j]);
                }));
                Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, new Action(() =>
                {
                    for (int j = 0; j < 100; j++)
                        container.Items.Remove(packages[j]);
                }));
            }
            Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.ApplicationIdle, new Action(() =>
            {
                GC.Collect();
            }));
        }
    }

    public class Shape : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        private double angle;
        public double Angle
        {
            get { return angle; }
            set
            {
                angle = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Angle)));
            }
        }

    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    InvestigateRequires further investigation by the WPF team.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions