Question

I am currently writing an app that mainly makes use of a DispatcherTimer to emulate Stopwatch functionality. While my DispatcherTimer is running within the app, my app's memory usage goes up to 100MB in less than 10 minutes which is especially weird considering how simple the app's functionality is. This wouldn't have normally been a problem except for the fact that the app's rapid increase in memory usage then causes it to crash and close out. I have looked all over the web and repeatedly have come across articles acknowledging the existence of a DispatcherTimer memory leak, however all of the fixes to this memory leak consist of stopping the DispatcherTimer when it is no longer needed. My memory leak occurs while the DispatcherTimer is still needed, not when it is accidentally left running. I need to allow for users to keep their stopwatch running for however long they choose, so stopping the DispatcherTimer when it's not needed anymore doesn't do much for me. I have tried adding GC.Collect() at the end of my TimerTick event handler, however, that didn't seem to do much either.

 public MainPage()
    {
        InitializeComponent();
        PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled;
        Timer.Stop();
        Timer.Interval = new TimeSpan(0, 0, 1);
        Timer.Tick += new EventHandler(TimerTick);
        Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);          

    }

 void TimerTick(object sender, EventArgs e)
    {

        timeSpan1 = DateTime.Now.Subtract(StartTimer);
        timeSpan2 = DateTime.Now.Subtract(StartTimer2);
        WatchHour.Text = timeSpan1.Hours.ToString();
        WatchMinute.Text = timeSpan1.Minutes.ToString();
        WatchSecond.Text = timeSpan1.Seconds.ToString();
        SecondaryHour.Text = timeSpan2.Hours.ToString();
        SecondaryMinute.Text = timeSpan2.Minutes.ToString();
        SecondarySecond.Text = timeSpan2.Seconds.ToString();


        if (WatchHour.Text.Length == 1) WatchHour.Text = "0" + WatchHour.Text;
        if (WatchMinute.Text.Length == 1) WatchMinute.Text = "0" + WatchMinute.Text;
        if (WatchSecond.Text.Length == 1) WatchSecond.Text = "0" + WatchSecond.Text;


        if (SecondaryHour.Text.Length == 1) SecondaryHour.Text = "0" + SecondaryHour.Text;
        if (SecondaryMinute.Text.Length == 1) SecondaryMinute.Text = "0" + SecondaryMinute.Text;
        if (SecondarySecond.Text.Length == 1) SecondarySecond.Text = "0" + SecondarySecond.Text;

    }

This is my TimerTick event handler and a bit of my MainPage constructor, the textboxes present in the event handler display the time elapsed from starting the stopwatch. Am I doing something specifically wrong here that is causing such a huge increase in memory? I had previously thought the issue was because the TextBoxes were somehow caching their previous contents by default coupled with rapid changes in text due to the stopwatch functionality, however, after completely removing the TextBoxes from my app and analyzing it, I am quite sure they aren't the problem. As stated above, adding GC.Collect() at the end of this TimerTick handler didn't do anything to decrease my memory usage. Does anyone have an idea of how I could reduce my memory usage with DispatcherTimer, maybe by somehow manipulating the GC function to actually work?

Thanks in advance!

Was it helpful?

Solution 3

I have finally isolated the core of my memory leak, the issue was not with my DispatcherTimer but instead with my AdRotator Control. The problem has been identified on the side of the AdRotator developers and I am currently using a different Ad control until the problem is fixed.

Thank you all for your help, I really appreciate your time and effort!

OTHER TIPS

Why are you declaring the timespan1 and timespan2 outside of the timer tick event? Does the memory look better if you create it inside of the event handler

Could you please try the following code snippet,

Step:1 Add the button and textblock in xaml first.

Step:2 Use the following namespaces:

using System.Diagnostics; // for Stopwatch API Access

Step:3 use the below mentioned code snippet:

public partial class WmDevStopWatch : PhoneApplicationPage
    {
        Stopwatch stopWatch = new Stopwatch();
        DispatcherTimer oTimer = new DispatcherTimer();

        public WmDevStopWatch()
        {
            InitializeComponent();

            oTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
            oTimer.Tick += new EventHandler(TimerTick);

        }

        void TimerTick(object sender, EventArgs e)
        {
            Dispatcher.BeginInvoke(() =>
             {
                 string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                     stopWatch.Elapsed.Hours, stopWatch.Elapsed.Minutes, stopWatch.Elapsed.Seconds,
                     stopWatch.Elapsed.Milliseconds / 10);

                 textBlock1.Text = elapsedTime;
             });
        }


        private void button1_Click(object sender, RoutedEventArgs e)
        {
            stopWatch.Start();
            oTimer.Start();
        }
    }

Hope it works for you.

Let me know your feedback for the same.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top