0

Actual Behavior:

  • Memory usage continuously increases over time
  • Memory is not being released even with proper disposal patterns implemented

Code Implementation:

using System.Collections.ObjectModel;

namespace MauiListView
{
    public class Message
    {
        public string? Content { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public partial class MainPage : ContentPage, IDisposable
    {
        private const int MAX_MESSAGES = 10;
        private readonly ObservableCollection<Message> messages;
        private IDispatcherTimer? timer;
        private bool isDisposed;

        public MainPage()
        {
            InitializeComponent();
            messages = new ObservableCollection<Message>();
            MessageListView.ItemsSource = messages;
        }

        private void StartMessageGeneration()
        {
            // 이전 타이머가 있다면 정리
            StopAndDisposeTimer();

            timer = Application.Current?.Dispatcher.CreateTimer();
            if (timer != null)
            {
                timer.Interval = TimeSpan.FromSeconds(1);
                timer.Tick += Timer_Tick;
                timer.Start();
            }
        }

        private void StopAndDisposeTimer()
        {
            if (timer != null)
            {
                timer.Stop();
                timer.Tick -= Timer_Tick; // 이벤트 핸들러 해제
                timer = null;
            }
        }

        private void Timer_Tick(object? sender, EventArgs e)
        {
            if (messages == null) return;

            var message = new Message
            {
                Content = $"새로운 메시지 {DateTime.Now}",
                Timestamp = DateTime.Now
            };

            MainThread.BeginInvokeOnMainThread(() =>
            {
                messages.Insert(0, message);
                while (messages.Count > MAX_MESSAGES)
                {
                    messages.RemoveAt(messages.Count - 1);
                }
            });
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!isDisposed)
            {
                if (disposing)
                {
                    StopAndDisposeTimer();
                    messages.Clear();
                    MessageListView.ItemsSource = null;
                }
                isDisposed = true;
            }
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            StartMessageGeneration();
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            StopAndDisposeTimer();
        }

        ~MainPage()
        {
            Dispose(false);
        }
    }
}

Environment:

  • .NET MAUI version: 8.0
  • Platform tested: Windows

What I've tried:

  1. Implemented IDisposable pattern
  2. Clearing ItemsSource on disposal
  3. Properly unsubscribing from events
  4. Limiting collection size with MAX_MESSAGES
  5. Using MainThread.BeginInvokeOnMainThread for UI updates

Expected Behavior:

  • ListView should maintain stable memory usage
  • Memory should be properly cleaned up when items are removed from the ObservableCollection
3
  • 2
    The intent of Dispose is to release unmanaged resources such as file or database locks. It's not intended intended for managed resources. learn.microsoft.com/en-us/dotnet/standard/garbage-collection/…. As to what happens between .NET and the garbage collector and when you expect to see releases in physical memory is a topic that's hard to summarize easily. But it is a misnomer that physical memory allocated shall be release immediately when you no longer refer to it. learn.microsoft.com/en-us/dotnet/standard/garbage-collection Commented Feb 5 at 8:57
  • 1
    How do you know that the memory is not released? Most likely, your observation is incorrect, because the usual methods of checking the memory are not accurate, and the memory is actually reclaimed by GC. It is not directly related to Dispose. Generally, you don't need Dispose unless you need to release unmanaged resources, or for some other special purposes. Commented Feb 5 at 22:07
  • Have you tried setting a cache strategy to improve the performance? such as<ListView CachingStrategy="RecycleElement"> Commented Feb 10 at 5:56

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.