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

Надявам се това да помогне...

Майк

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