Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[controls] fix memory leak with Grid Row/ColumnDefinitions #16145

Merged
merged 1 commit into from
Jul 18, 2023

Commits on Jul 13, 2023

  1. [controls] fix memory leak with Grid Row/ColumnDefinitions

    Context: dotnet#15860
    
    In a customer's app, they have the setup:
    
        <!-- Resources/Styles/Styles.xaml -->
        <Style TargetType="Grid" x:Key="GridStyleWithColumnDefinitions">
            <Setter Property="ColumnDefinitions" Value="18,*"/>
        </Style>
    
    Then a page with:
    
        <Grid Style="{StaticResource GridStyleWithColumnDefinitions}" />
    
    Navigating forward & back from this page would show that the entire
    `Page` would live forever! What is interesting, is simply removing the
    Grid's `Style` solved the problem?!?
    
    I narrowed this down to a unit test:
    
        [Fact]
        public async Task ColumnDefinitionDoesNotLeak()
        {
            // Long-lived column, like from a Style in App.Resources
            var column = new ColumnDefinition();
            WeakReference reference;
    
            {
                var grid = new Grid();
                grid.ColumnDefinitions.Add(column);
                reference = new(grid);
            }
    
            await Task.Yield();
            GC.Collect();
            GC.WaitForPendingFinalizers();
    
            Assert.False(reference.IsAlive, "Grid should not be alive!");
        }
    
    https://github.com/dotnet/maui/blob/cda3eb3381cfb686567ed05e3eb8e8f26c02d785/src/Controls/src/Core/Layout/Grid.cs#L20
    
    `Grid` subscribes to `DefinitionCollection<T>.ItemSizeChanged`, and in
    this case the `DefinitionCollection<T>` lived indefinitely in an
    application-wide `ResourceDictionary`.
    
    The simplest solution is to make the `ItemSizeChanged` event use
    `WeakEventManager` as was done for other events like
    `Application.RequestedThemeChanged`:
    
    https://github.com/dotnet/maui/blob/cda3eb3381cfb686567ed05e3eb8e8f26c02d785/src/Controls/src/Core/Application/Application.cs#L221-L225
    
    Since MAUI owns the property, we can use the simple solution here.
    
    This is one issue solved in the customer app, but I will need to retest
    the app in dotnet#15860 to see if there are further issues.
    jonathanpeppers committed Jul 13, 2023
    Configuration menu
    Copy the full SHA
    20cb950 View commit details
    Browse the repository at this point in the history