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

2

Я пишу класс 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". Есть ли у меня ошибка в коде?

  • 1
    «Dispose» предназначен для освобождения объектов, но вы используете его для логики приложения, а именно для выхода из Excel. Переместите ваш метод выхода в другое место и не полагайтесь на Dispose, чтобы выйти из Excel для вас, вы должны сделать это самостоятельно.
Теги:
excel
release
idisposable

1 ответ

2
Лучший ответ

Как объясняется в моем ответе на ваш другой связанный с нами вопрос здесь, вы не должны предпринимать действия над ссылочными типами из своего финализатора. Вы применяете это, используя параметр 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 statement, Dispose метод на вашем классе "MSExcel" будет вызываться автоматически, гарантируя, что excel.Quit() называется детерминированным, а не из финализатора.

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

Mike

  • 0
    Предполагая, что кто-то имеет дело с методом Quit класса Excel.Application, предоставление True значения первому параметру (SaveChanges) предотвращает возможное зависание во время процесса закрытия, когда есть ожидающие изменения. Это должно быть серьезной проблемой, когда свойство Visible в Excel.Application установлено в False, что происходит в основном во время процессов автоматизации.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню