7

I have created a Windows Forms application in .NET 2 using C# that runs continuously. For most accounts I am pleased with it, but it has been reported to me that it has failed occasionally. I am able to monitor its performance for 50% of the time and I have never noticed a failure.

At this point I am concerned that perhaps the program is using too many resources and is not disposing of resources when they are no longer required.

What are the best practices for properly disposing created objects that have created timers and graphical objects like graphics paths, SQL connections, etc. or can I rely on the dispose method to take care of all garbage collection?

Also: Is there a way that I could monitor resources used by the application?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Brad
  • 20,302
  • 36
  • 84
  • 102
  • is your code all managed code without unsafe, dllimport and so on ? – VolkerK May 02 '09 at 13:00
  • Those reports about failures, do they include exception information, or anything at all that can be used to reproduce the problem? Does the whole application fail, or just a single method call? You could try listening on AppDomain.UnhandledException to log any exceptions that isnt handled, but any silent catch {} is considered handled and as such wont be logged. – sisve May 02 '09 at 20:59

7 Answers7

14

Best practice is to make sure that all objects implementing the IDisposable interface is called Dispose on as soon as the object is no longer required.

This can be accomplished either with the using keyword or try/finally constructs.

Within a WinForms form that has resources allocated for the lifetime of the form, a somewhat different approach is necessary. Since the form itself implements IDisposable this is an indication that at some point in time Dispose will be called on this form. You want to make sure that your disposable resources gets disposed at the same time. To do this you should override the forms Dispose(bool disposing) method. The implementation should look something like this:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        // dispose managed resources here
    }
    // dispose unmanaged resources here
}

A note on Components in forms: if your object implements the IComponent interface you can place the instance in the forms Container. The container will take care of disposing components when the container itself is disposed.

Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131
  • Hi, It doesnt allow me to dispose it. It says "member with the same signature is already declared". How do you override a Dispose inherited from Form ? Thanks – Houman Sep 18 '09 at 16:32
  • I take it I have to use the same override method as in Designer code? – Houman Sep 18 '09 at 16:45
  • Kave - do you see in the .Designer.cs file a Dispose method as the one in my sample above? If so, what is it doing? You could post it here as a question to get more feedback on what can be done... – Peter Lillevold Sep 19 '09 at 00:20
4

In addition to what's already been said, if you're using COM components it's a very good idea to make sure that they are fully released. I have a snippet that I use all the time for COM releases:

private void ReleaseCOMObject(object o)
{
   Int32 countDown = 1;
   while(countDown > 0)
       countDown = System.Runtime.InteropServices.Marshal.ReleaseCOMObject(o);
}
AJ.
  • 16,368
  • 20
  • 95
  • 150
2

You should call Dispose on scarce resources to free them. You can use a using statement for that matter:

using (var resource = new MyScarceObject()) 
{
    // resource will be used here...
} // will free up the resources by calling Dispose automatically
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
2

There are a few ways of ensuring this. The main help I find is by utilising the "using" keyword. This is applied as such:

using(SqlConnection connection = new SqlConnection(myConnectionString))
{
    /* utilise the connection here */ 
}

This basically translates into:

SqlConnection connection = null;
try
{
    connection = new SqlConnection(myConnectionString);
}
finally
{
    if(connection != null) connection.Dispose();
}

As such it only works with types that implement IDisposable.

This keyword is massively useful when dealing with GDI objects such as pens and brushes. However there are scenarios where you will want to hold onto resources for a longer period of time than just the current scope of a method. As a rule it's best to avoid this if possible but for example when dealing with SqlCe it's more performant to keep one connection to the db continuously open. Therefore one can't escape this need.

In this scenario you can't use the "using" but you still want to be able to easily reclaim the resources held by the connection. There are two mechanisms that you can use to get these resources back.

One is via a finaliser. All managed objects that are out of scope are eventually collected by the garbage collector. If you have defined a finaliser then the GC will call this when collecting the object.

public class MyClassThatHoldsResources
{
    private Brush myBrush;

    // this is a finaliser
    ~MyClassThatHoldsResources()
    {
       if(myBrush != null) myBrush.Dispose();
    }
}

However the above code is unfortunately crap. The reason is because at finalizing time you cannot guarantee which managed objects have been collected already and which have not. Ergo the "myBrush" in the above example may have already been discarded by the garbage collector. Therefore it isn't best to use a finaliser to collect managed objects, its use is to tidy up unmanaged resources.

Another issue with the finaliser is that it is not deterministic. Lets say for example I have a class that communicates via a serial port. Only one connection to a serial port can be open at one time. Therefore if I have the following class:

class MySerialPortAccessor
{
    private SerialPort m_Port;

    public MySerialPortAccessor(string port)
    {
        m_Port = new SerialPort(port);
        m_Port.Open();
    }

    ~MySerialPortAccessor()
    {
        if(m_Port != null) m_Port.Dispose();
    }
}

Then if I used the object like this:

public static void Main()
{
    Test1();
    Test2();
}

private static void Test1()
{
    MySerialPortAccessor port = new MySerialPortAccessor("COM1:");
    // do stuff
}

private static void Test2()
{
    MySerialPortAccessor port = new MySerialPortAccessor("COM1:");
    // do stuff
}

I would have a problem. The issue is that the finaliser is not deterministic. That is to say I cannot guarantee when it will run and therefore get round to disposing my serial port object. Therefore when I run test 2 I might find that the port is still open. While I could call GC.Collect() between Test1() and Test2() which would solve this problem it isn't recommended. If you want to get the best performance out of the collector then let it do its own thing.

Therefore what I really want to do is this:

class MySerialPortAccessor : IDispable
{
    private SerialPort m_Port;

    public MySerialPortAccessor(string port)
    {
        m_Port = new SerialPort(port);
        m_Port.Open();
    }

    public void Dispose()
    {
        if(m_Port != null) m_Port.Dispose();
    }
}

And i'll rewrite my test like this:

public static void Main()
{
    Test1();
    Test2();
}

private static void Test1()
{
    using( MySerialPortAccessor port = new MySerialPortAccessor("COM1:"))
    {
        // do stuff
    }
}

private static void Test2()
{
    using( MySerialPortAccessor port = new MySerialPortAccessor("COM1:"))
    {
        // do stuff
    }
}

This will now work. So what of the finaliser? Why use it?

Unmanaged resources and possible implementations that don't call Dispose.

As the writer of a component library that others use; their code may forget to dispose of the object. It's possible that something else might kill the process and hence the .Dispose() would not occur. Due to these scenarios a finaliser should be implemented to clean any unmanaged resource as a "worst case" scenario but Dispose should also tidy these resources so you have your "deterministic clean up" routine.

So in closing, the pattern recommended in the .NET Framework Guidelines book is to implement both as follows:

public void SomeResourceHoggingClass, IDisposable
{
    ~SomeResourceHoggingClass()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    // virtual so a sub class can override it and add its own stuff
    //
    protected virtual void Dispose(bool deterministicDispose)
    {    
         // we can tidy managed objects
         if(deterministicDispose)
         {
              someManagedObject.Parent.Dispose();
              someManagedObject.Dispose();
         }

         DisposeUnmanagedResources();

         // if we've been disposed by .Dispose()
         // then we can tell the GC that it doesn't
         // need to finalise this object (which saves it some time)
         //
         GC.SuppressFinalize(this);
    }
}
Quibblesome
  • 25,225
  • 10
  • 61
  • 100
1

A few tips:

-Take advantage of the Using() keyword whenever you can. If you have unit tests in place I would recommend refactoring your code to implement this change.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

-Remember to explicitly unregister all event handlers and remove all objects from lists that live for the entire duration of your application. This is the most common mistake that programmers make in .NET that results in these items not being collected.

Robert Venables
  • 5,943
  • 1
  • 23
  • 35
1

As for monitoring the built in perfmon (2) works fine for memory usage etc. If you're worried about file handles, dll handles, etc I recommend Process Explorer and Process Monitor

C. Ross
  • 31,137
  • 42
  • 147
  • 238
1

When an object is inaccessible, the Object.Finalize Method will get called. It is helpful to suppress this unnecessary call in your classes that implement IDisposable. You can do this by calling the GC.SuppressFinalize Method

public void Dispose()
{
    // dispose resources here

    GC.SuppressFinalize(this);
}
John Nelson
  • 5,041
  • 6
  • 27
  • 34