1

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!

  • How about stopping the timer at the beggining of the tick event, And starting it again at the end? – Nir Kornfeld Aug 25 '13 at 19:16
  • 1
    I don't think problem is with above code. Culprit it somewhere else I suspect. BTW use `WatchHour.Text = timeSpan1.Hours.ToString("00");` to achieve correct formatting as you need – Sriram Sakthivel Aug 25 '13 at 19:36
  • Does you app crash if you let it run, or does the memory stop increasing at some point? – Kevin Gosse Aug 25 '13 at 20:46
  • The memory never stops increasing and if I let it run long enough, it will always crash –  Aug 26 '13 at 03:15
  • @NirKornfeld I tried adding stopping and then starting my timer within my Tick event but the problem remains –  Aug 26 '13 at 04:43
  • So here's something weird I found, even when the DispatcherTimers are not started, the memory usage increases at the same rate. –  Aug 26 '13 at 04:52
  • @user2637236 It isn't surprising, we had long figured out that your `TimerTick` method couldn't possibly use 100MB of RAM ;) Are you using `Image` controls somewhere in the app? – Kevin Gosse Aug 26 '13 at 05:50
  • I'm not using an Image control, however, my buttons use images as their background. I am using an AdRotator control and a coding4fun Toolkit TimeSpanPicker control as for the more 'unusual' controls. Could these be a problem? As you can see in my code snippet I call a MainPage_Loaded handler to Invalidate my AdRotator control in my MainPage constructor and because the memory issue comes in by opening the app without any user input, that could be a possibility –  Aug 26 '13 at 10:06

3 Answers3

0

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

Ken Tucker
  • 4,126
  • 1
  • 18
  • 24
  • It looks like the memory usage is the same, however, you did help simplify my code a bit! –  Aug 26 '13 at 03:28
0

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.

Pavan
  • 533
  • 5
  • 15
0

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!

  • Can you please share the details of what was the problem in the control? Was it possible the issue was due to a cyclic reference? Can cyclic reference cause a drastic increase in memory? – Ritesh Kumar Oct 12 '22 at 07:45