Showing posts with label IDisposable Interface. Show all posts
Showing posts with label IDisposable Interface. Show all posts

Sunday, March 25, 2012

Implementing IDisposable Interface Part - II

In previous post we discussed implementing IDisposable interface for unmanaged code. Even though your class may implement IDisposable interface and you release the resources, but what if a developer never calls the dispose method? Since GC can't free up resources claimed by your unmanaged code and if you forgot to call Dispose method, you are back to square one.

What if we somehow force Garbage Collector to call the Dispose method for our unmanaged code? This will be best of both worlds - you can free up resources as soon as you are done, but if you forgot to free up resources, you can be sure that GC at some point will reclaim those resources. In order to force GC to free up unmanaged resources, you have to implement your own version of Finalize method. GC will use this finalize method to destroy your objects. Declaring a finalize method in C# is similar to destructor method you create in C++

Lets extend the class we created in previous post.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace IDisposableInterface
{
    class Unmanaged:IDisposable
    
    {
        private bool _disposed;
        private IntPtr _handle;

        //initializer method 
        public Unmanaged()
    {
        //we create a new pointer and associate it with the current process
        // This is unmanaged code and _handle must be disposed explicity 
        //and GC will not collect it
         _handle = new IntPtr();
        _handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
    }
        public IntPtr Handle
        {
            get { return _handle; }
        }
      //notice we have declared this method as private because this is not thread      -safe 
      //and should only be called once. Here we are declaring a global variable        //to ensure it only executes once.
       private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                //release unmanaged resources
                 _handle = IntPtr.Zero;
                _disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
        }
       //Create Finalize Method. This will be called by GC to dispose off 
       //unmanaged resources.
       ~Unmanaged()
       {
          Dispose(true);
       }
    }
}

While this works, but you could be destroying an object twice and may result in an error. Even if it doesn't result in an error, you are still unnecessarily calling Dispose more than once. What if you can design it in a way that GC only calls your dispose method only when you haven't called it? You can do this by modifying your Dispose method and adding SuppressFinalize.

public void Dispose()
        {
            Dispose(true);
            //don't bother trying to dispose this object.
            GC.SuppressFinalize(this); 
        }

Now, if you have called the Dispose method yourself, you have directed GC to don't bother disposing this object. If you didn't call Dispose method, GC will take care of it.

In reality, most classes that have some unmanaged code almost always have the managed code as well. Wouldn't it be nice to dispose off your managed resources when you destroy your unmanaged resources as well? GC will eventually destroy your managed resources, but why wait when you know you don't need them anymore? Especially if they consume large amount of memory. Let's modify the above class and create a handle to read a file from the hard-drive.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace IDisposableInterface
{
    class Unmanaged:IDisposable
    
    {
        private bool _disposed;
        private IntPtr _handle;
        private System.IO.Stream _filestream;   //managed resource
        //initializer method 
        public Unmanaged()
    {
        //we create a new pointer and associate it with the current process
        // This is unmanaged code and _handle must be disposed explicity 
        //and GC will not collect it
         _handle = new IntPtr();
        _handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
        _filestream = System.IO.File.Open(@"c:\temp\TestFile.txt", 
                                          System.IO.FileMode.Open);
    }
        public IntPtr Handle
        {
            get { return _handle; }
        }
        public long FileSize
        {
            get { return _filestream.Length; }
        }
      //notice we have declared this method as private because this is not thread      -safe 
      //and should only be called once. Here we are declaring a global variable        //to ensure it only executes once.
       private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                 {
                    //release managed resources
                    if (_filestream !=null) _filestream.Dispose();
                 }
                 //release unmanaged resources
                 _handle = IntPtr.Zero;
                _disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
            //don't bother trying to dispose this object.
            GC.SuppressFinalize(this);
        }
       //Create Finalize Method. This will be called by GC to dispose off 
       //unmanaged resources.
       ~Unmanaged()
       {
          Dispose(false);
       }
    }
}

Notice few things that I changed in this class. First, I created a _fileStream object which is a managed resource. Then in Dispose method, I disposed this object along with unmanaged resource i.e. IntPtr. But I also did something else, which is very important when you are disposing managed resources yourself. In ~Unamanged destructor, I am now passing "false" for disposing. Since GC runs in background and doesn't destroy objects in order they were created, it is entirely possible that _filestream object was already destroyed before GC called your version of Finalize method (destructor). You want to make sure that when you manually call Dispose, you dispose off both managed and unmanaged resources (GC couldn't dispose off managed resource then because object is still in use), but if you let GC call your destructor, you shouldn't dispose managed resources since GC may have already disposed it.

Even if you are using managed resources, it is a good practice to dispose off your objects especially if they are large and consume lot of memory (such as collection of images) as soon as your are done using it. But, you must be careful to design your dispose methods in such a way that you don't interfere with GC.

Thank you.

Friday, March 23, 2012

Implementing IDisposable Interface-Part I

In previous posts we discussed ICmparer and IComparable interfaces, today we will discuss another important interface called IDisposable. Before we dive into its implementation, lets refresh our memory on how things were before .NET framework.

Before .NET Framework, if you initialized an object such as opening a database connection, you must manually dispose it. You could eventually bring your system to its knees, if you forgot to dispose your objects.

Framework solved this problem by introducing the concept of Garbage Collector. GC runs on a background thread and uses complex mechanism to determine which initialized objects are no longer being used and can be safely destroyed. It then disposes those objects for you. There is only one caveat - it can only dispose the managed objects i.e. the objects that are part of the .NET Framework library. If you invoke a non managed resource such as an IntPtr to acquire a Windows Handle or some other unmanaged resource (via PInvoke), you are on your own and must dispose them.

Framework provides an IDisposable interface with a Dispose method that you can implement in classes which will initialize and consume unmanaged resources.

Let's see an example.

In this example, we will obtain the handle associated with current process and assign it to a variable of type IntPtr which is unmanaged and must be disposed manually. We will implement Dispose method and then dispose this object.

Unmanaged Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace IDisposableInterface
{
    class Unmanaged:IDisposable
    
    {
        private bool _disposed;
        private IntPtr _handle;

        //initializer method 
        public Unmanaged()
    {
        //we create a new pointer and associate it with the current process
        // This is unmanaged code and _handle must be disposed explicity 
        //and GC will not collect it
         _handle = new IntPtr();
        _handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
    }
        public IntPtr Handle
        {
            get { return _handle; }
        }
      //notice we have declared this method as private because this is not thread-safe 
      //and should only be called once. Here we are declaring a global variable _declared 
        //to ensure it only executes once.
       private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                //release unmanaged resources
                 _handle = IntPtr.Zero;
                _disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
        }

    }
}


Dispose method is not thread-safe and in a multi-threaded application you must use synclock before calling this method. Also, you cannot dispose an object once it is disposed, so care must be taken to dispose it only once. In above class, we have declared a private Dispose method to ensure we only dispose an object once.

Calling the Dispose Method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IDisposableInterface
{
    class Program
    {
        static void Main(string[] args)
        {
            // instantiate unmanaged class and retrieve the handle
            Unmanaged notManaged = new Unmanaged();
            Console.WriteLine("Handle:={0}", notManaged.Handle);
            //Dispose
            notManaged.Dispose();
            Console.Read();
        }
    }
}


Since this is unmanaged code, GC will not dispose it so there are no worries, but if you were using managed code and had implemented your own dispose method, you will have to ensure GC doesn't try to dispose the object that you have already disposed.

We will see how to properly implement your own dispose method for managed code and what may be the advantages of doing so in the next post.

Thank you.