2

I am writing an excel class and i want to release this unmanaged object automatically. I'm using IDisposable pattern and write Dispose methods. Example ;

class MSExcel : IDisposable
{
    ApplicationClass excel;
    bool disposed;

    public MSExcel()
    {
         disposed = false;
         excel = new ApplicationClass();
    }

    public void Dispose(bool disposing)
    {
        if (!this.disposed)
        {

            if (disposing)
            {

            }

            excel.Quit();                
            disposed = true;

        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~MSExcel()
    {
       Dispose(false);
    }
}

But i have classical error on exc.Quit(). "COM object that has been separated from its underlying RCW". Have any my mistake in code?

Mike Rosenblum
  • 12,027
  • 6
  • 48
  • 64
Murat
  • 803
  • 4
  • 15
  • 27
  • 1
    "Dispose" is meant for releasing objects but you're using it for application logic, namely quitting Excel. Move your quit method elsewhere and don't rely on Dispose to quit Excel for you, you should do that on your own. – Chris Haas Jan 18 '10 at 21:51

1 Answers1

2

As explained in my answer to your other related question here, you should not be taking actions on reference types from within your finalizer. You enforce this by making use of the bool disposing parameter of your Disposed(bool) method, as you have done. You pass in true, when Disposed(bool) is called explicitly from the void Dispose() method, and pass in false when called from your finalizer, which you have also done.

However, you also need to protect your call to excel.Quit() so that it is not called when Disposed(bool) is called via the finalizer. That is, you should only call excel.Quit() when the bool disposing argument is true.

Therefore, the code for your Disposed(bool) method should look as follows:

public void Dispose(bool disposing)
{
    if (!this.disposed)
    {

        if (disposing)
        {
            excel.Quit();   
        }

        disposed = true;
    }
}

Once done, you could make use of your "MSExcel" class as follows:

using (MSExcel msExcel = new MSExcel)
{
   // The code calling your 'MSExcel' object goes here.
}

By doing it this way, when your code gets to the closing bracket, "}", of your using statement block, the Dispose method on your 'MSExcel' class will be called automatically, ensuring that excel.Quit() is called deterministically, and not from a finalizer.

Hope this helps...

Mike

Community
  • 1
  • 1
Mike Rosenblum
  • 12,027
  • 6
  • 48
  • 64
  • Assuming one is dealing with Excel.Application class's Quit method, providing True value to first parameter (SaveChanges) prevents possible hanging during the close process, when there are pending changes. This should be a major concern when Excel.Application's Visible property is set to False, which happens mostly during automation processes. – Julio Nobre Nov 02 '16 at 23:54