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 leak in ImageSource, caused by Task that never completes #21928

Merged

Commits on Apr 18, 2024

  1. [controls] fix leak in ImageSource, caused by Task that never completes

    Context: https://github.com/AdamEssenmacher/MemoryToolkit.Maui/tree/main/samples
    
    Testing the above sample, I saw some odd results in a `.gcdump`
    related to `UriImageSource` inside a `CollectionView`:
    
        AsyncTaskMethodBuilder+AsyncStateMachineBox<VoidTaskResult, Microsoft.Maui.Controls.ImageElement+<CancelOldValue>d__10>, Count: 182
            Dictionary+Entry<Int32, Task>[], Count: 182
                Dictionary<Int32, Task> [Static variable Task.s_currentActiveTasks], Count: 1
    
    It appears that we `await` a `Task` that never completes, which is:
    
    https://github.com/dotnet/maui/blob/8e4450cbc14932a6c74aeb8b7bfee9c94eca18b0/src/Controls/src/Core/ImageElement.cs#L129
    
    The `Task` also holds onto the `ImageSource` and whatever memory it
    happened to use. That would be ok if the `Task` completed.
    
    I could reproduce the problem in a test:
    
        [Fact]
        public async Task CancelCompletes()
        {
            var imageSource = new StreamImageSource
            {
                Stream = _ => Task.FromResult<Stream>(new MemoryStream())
            };
            await ((IStreamImageSource)imageSource).GetStreamAsync();
            await imageSource.Cancel(); // This should complete!
        }
    
    This non-completing `Task` can occur when changing `Image.Source`,
    which would certainly be bad while scrolling a `CollectionView`!
    
    To fix, I refactored the code slightly and had the problematic case
    return:
    
        return Task.FromResult(false);
    jonathanpeppers committed Apr 18, 2024
    Configuration menu
    Copy the full SHA
    5ecbcda View commit details
    Browse the repository at this point in the history