RomulanPaladin
RomulanPaladin

Reputation: 3

Small Memory Leak

New to threading, delegates, and garbage collection.

I have a C# program in Visual Studio 2013 that runs a loop on background thread to constantly update controls on a form in my main thread. While the loop is running (and only when the loop is running), Performance Monitor shows a small but steady increase in Private Bytes for that program.

When the background thread is stopped and joined, there is no decrease in the Private Bytes usage but it no longer increases. This program needs to run a long time with the looping thread so a small leak could become a problem after hours / days.

I can comment out the lines in the loop where it calls for the update method; this successfully curbs the issue. What am I doing to prevent garbage collection in that method?

P.S.: If you point me to a program for looking through the heap, please give me a step-by-step on how to install and use it. I've been a little burned out lately and what I've seen online so far isn't obvious enough for my brain at the moment.

    private IAsyncResult iar;  // Store the IAsyncResult to check for completion the next time I call it.

    public delegate void Assisted_UpdateTimer(int totalSeconds, int secondsElapsed, int secondsRemaining);
    public void UpdateTimer(int totalSeconds, int secondsElapsed, int secondsRemaining)
    {
        if (this.InvokeRequired || pbTimeBar.InvokeRequired)  // If we need to be threadsafe
        {
            if (iar != null)  // If we've invoked something before
            {
                if (iar.IsCompleted)  // If the last thing we invoked has completed
                {
                    this.EndInvoke(iar);
                    Assisted_UpdateTimer _delegate = new Assisted_UpdateTimer(UpdateTimer);
                    iar = this.BeginInvoke(_delegate, totalSeconds, secondsElapsed, secondsRemaining);
                }
            }
            else  // Invoke for the first time
            {
                Assisted_UpdateTimer _delegate = new Assisted_UpdateTimer(UpdateTimer);
                iar = this.BeginInvoke(_delegate, totalSeconds, secondsElapsed, secondsRemaining);
            }
        }
        else  // The actual method code
        {
            TimeSpan timeElapsed = new TimeSpan(0, 0, secondsElapsed);
            TimeSpan timeRemaining = new TimeSpan(0, 0, secondsRemaining);
            int percent = (int)(((double)secondsElapsed / (double)totalSeconds) * 100);

            if (pbTimeBar.Maximum != totalSeconds) pbTimeBar.Maximum = totalSeconds;
            if (secondsElapsed >= 0) pbTimeBar.Value = secondsElapsed;  // pbTimeBar is a progress bar

            // Add text to progress bar
            pbTimeBar.CreateGraphics().DrawString(percent + "%", new Font("Arial", (float)8.25, FontStyle.Regular), new SolidBrush(Color.FromArgb(255, 0, 0, 0)), new PointF(pbTimeBar.Width / 2 - 10, pbTimeBar.Height / 2 - 7));

            labElapsed.Text = string.Format("{0:00}:{1:00}:{2:00} Elapsed", timeElapsed.Hours, timeElapsed.Minutes, timeElapsed.Seconds);
            labRemaining.Text = string.Format("Remaining {0:00}:{1:00}:{2:00}", timeRemaining.Hours, timeRemaining.Minutes, timeRemaining.Seconds);

            trayIcon.Text = string.Format("Toast Timer\nRemaining: {0:00}:{1:00}:{2:00}\nElapsed: {3}%", timeRemaining.Hours, timeRemaining.Minutes, timeRemaining.Seconds, percent);
        }
    }

Upvotes: 0

Views: 141

Answers (1)

brainless coder
brainless coder

Reputation: 6430

I haven't checked your full code but the memory leak could be a possible output of strong delegate reference. You see, when you attach a delegate to the event of an object, the object will never be garbage collected unless the delegate reference is removed manually. Here is a documentation reference from msdn to help you understand the scenario better and with possible solutions -

http://msdn.microsoft.com/en-us/library/aa970850(v=vs.110).aspx

Listening for events can lead to memory leaks. The typical technique for listening to an event is to use the language-specific syntax that attaches a handler to an event on a source. For example, in C#, that syntax is: source.SomeEvent += new SomeEventHandler(MyEventHandler).

And for the last part of your question - I usually use Ant Profiler for memory testing. It is not free but the trial version usually works and gives you enough time to solve the issue.

http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/

http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/

Comment: I am guessing repeating call to UpdateTimer could make a possible memory leak if it is attaching new delegates in each call.

Upvotes: 1

Related Questions