Как выпустить объект Excel с интерфейсом IDisposeable

Я пишу класс Excel и хочу автоматически освободить этот неуправляемый объект. Я использую шаблон IDisposable и пишу методы Dispose. Пример ;

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);
    }
}

Но у меня классическая ошибка exc.Quit (). «COM-объект, который был отделен от основного RCW». Есть ли у меня ошибка в коде?


person Murat    schedule 18.01.2010    source источник
comment
Dispose предназначен для освобождения объектов, но вы используете его для логики приложения, а именно для выхода из Excel. Переместите свой метод выхода в другое место и не полагайтесь на Dispose для выхода из Excel за вас, вы должны сделать это самостоятельно.   -  person Chris Haas    schedule 19.01.2010


Ответы (1)


Как объясняется в моем ответе на другой связанный с вами вопрос, здесь, вам не следует предпринимать действия со ссылочными типами из финализатора. Вы обеспечиваете это, используя параметр bool disposing вашего Disposed(bool) метода, как вы это сделали. Вы передаете true, когда Disposed(bool) вызывается явно из метода void Dispose(), и передаете false при вызове из вашего финализатора, что вы также сделали.

Однако вам также необходимо защитить свой вызов excel.Quit(), чтобы он не вызывался, когда Disposed(bool) вызывается через финализатор. То есть вы должны вызывать excel.Quit() только тогда, когда аргумент bool disposing равен true.

Следовательно, код вашего Disposed(bool) метода должен выглядеть следующим образом:

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

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

        disposed = true;
    }
}

После этого вы можете использовать свой класс «MSExcel» следующим образом:

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

Таким образом, когда ваш код доходит до закрывающей скобки "}" вашего using оператор, метод Dispose в вашем классе 'MSExcel' будет вызываться автоматически, гарантируя, что excel.Quit() вызывается детерминированно, а не из финализатора.

Надеюсь это поможет...

Майк

person Mike Rosenblum    schedule 18.01.2010
comment
Предполагая, что один из них имеет дело с методом Quit класса Excel.Application, предоставление значения True первому параметру (SaveChanges) предотвращает возможное зависание во время процесса закрытия, когда есть ожидающие изменения. Это должно стать серьезной проблемой, если для свойства Visible Excel.Application установлено значение False, что чаще всего происходит во время процессов автоматизации. - person Julio Nobre; 03.11.2016