0

I have a polling thread which calls the following function and then sleeps for 20 seconds or so. I have been trying to determine why my application (a C# form) accumulates memory requirements up to 500Kbs over the duration of the application. When I remove the polling thread it appears to have a small constant memory usage over the duration of the application. I have concluded that the accessControl method within the thread is not freeing resources appropriately when it leaves the scope. Anyone familiar with this?

    // Method that accesses Form objects that must be accessed by original thread
    private void accessControl()
    {
        int secCount = 600;
        bool[] newViolation;
        bool tempBool = false;
        tempBool = label3.InvokeRequired || labelSecondLargest.InvokeRequired || labelThirdLargest.InvokeRequired;
        if (tempBool)
        {
            System.Console.WriteLine("CHANGING LABELS");
            labelLargest.Invoke(new MethodInvoker(delegate
            {
                newViolation = checkViolations();
                Draw(Assets);
                Thread.Sleep(secCount);
                int counter = 0;
                int duration = 3;
                while(counter < duration)
                {
                    if(newViolation[0])
                        labelLargest.ForeColor = System.Drawing.Color.Red;
                    if (newViolation[1])
                        labelSecondLargest.ForeColor = System.Drawing.Color.Red;
                    if (newViolation[2])
                        labelThirdLargest.ForeColor = System.Drawing.Color.Red;

                    System.Windows.Forms.Application.DoEvents();
                    Thread.Sleep(secCount);                         // Wait secCount/1000 seconds before moving on...
                    if (newViolation[0])
                        labelLargest.ForeColor = System.Drawing.Color.Blue;
                    if (newViolation[1])
                        labelSecondLargest.ForeColor = System.Drawing.Color.Green;
                    if (newViolation[2])
                        labelThirdLargest.ForeColor = System.Drawing.Color.Purple;
                    counter++;                                      // Do this 'counter' many times
                }
            }));
        }
        else
        {
           System.Console.WriteLine("CHANGING LABELS 2");
           newViolation = checkViolations();
           Draw(Assets);
           Thread.Sleep(secCount);
           int counter = 0;
           int duration = 3;
           while(counter < duration)
           {
                if(newViolation[0])
                    labelLargest.ForeColor = System.Drawing.Color.Red;
                if (newViolation[1])
                    labelSecondLargest.ForeColor = System.Drawing.Color.Red;
                if (newViolation[2])
                    labelThirdLargest.ForeColor = System.Drawing.Color.Red;

                System.Windows.Forms.Application.DoEvents();
                Thread.Sleep(secCount);                         // Wait secCount/1000 seconds before moving on...
                 if (newViolation[0])
                    labelLargest.ForeColor = System.Drawing.Color.Blue;
                 if (newViolation[1])
                    labelSecondLargest.ForeColor = System.Drawing.Color.Green;
                 if (newViolation[2])
                     labelThirdLargest.ForeColor = System.Drawing.Color.Purple;
                }
            }
        }
    // **********************************************************************************************************************************************************************
Erroldactyl
  • 383
  • 1
  • 7
  • 17
  • I would look at the `Draw(Assets)`; Perhaps there is some graphical resource there that isn't freed. – xanatos Aug 13 '13 at 19:56
  • Why are you doing this in a thread rather than on a timer? Furthermore, why are you sleeping on the UI thread? Also, what are you using to determine memory usage? Is it continually increasing, or does it stop at 500 KB? – Jim Mischel Aug 13 '13 at 19:56
  • @JimMischel I'm sleeping on the thread in this loop to give off the effect of a blinking message (the colors change, sleep, and change back). Also, I have been checking the memory usage of my application under the task manager and that figure continues to increase slowly without any limit. – Erroldactyl Aug 13 '13 at 20:01
  • 1
    Most application only have one UI thread, in which case you don't need to bother with checking InvokeRequired on more than one control (such as the form itself). Also check various ways to avoid the code duplication: http://stackoverflow.com/questions/2367718/automating-the-invokerequired-code-pattern – Oskar Berggren Aug 13 '13 at 20:02
  • 1
    Don't thread sleep to perform UI animations. Use a timer instead. – asawyer Aug 13 '13 at 20:07
  • @xanatos You are right on with this. This was creating new datagridview objects that were not being properly destroyed at the next call of Draw(Assets). I fixed this by making those global variables and checking for null before instantiating them in Draw(Assets). – Erroldactyl Aug 13 '13 at 21:52

1 Answers1

0

As someone mentioned, the Draw(Assets) method was the source of the problem. The method was responsible for declaring and instantiating new DataGridView objects that represented the different tabs in the winform.

This however always created new DataGridView objects without properly removing the old ones (I suppose that, since this is a form property, the normal memory management didn't apply once out of Draw()'s scope).

To fix this I made those variables global and instantiated them only when there were not existent (null).

Erroldactyl
  • 383
  • 1
  • 7
  • 17
  • 1
    Nearly all the objects of WinForms are `IDisposable`. Even the `Image`, `Bitmap`, `Font`, ... are `IDisposable`. You should manually dispose them when you stop using them, if you do it often. – xanatos Aug 14 '13 at 05:11