Выпуск Excel Object In My Destructor

Я пишу использованию класса Excel Microsoft. Interropt. Excel DLL. Я заканчиваю всю функцию, но у меня есть ошибка в моем Деструкторе. Я Хочу сохранить все изменения в своем файле, и я хочу выпустить весь источник. Я хочу всем им в моем деструкторе. Но В моем деструкторе, Excel. ApplicationClass, Рабочая книга и объекты Рабочего листа являются заливкой Исключением, которые имеют сообщение "COM-объект, который был разделен от его базового RCW, не может использоваться". Таким образом, я ничего не могу сохранить, ничего не закрыть, потому что ı не может получить доступ к рабочей книге или объекту рабочего листа.

Разве я не могу получить доступ к членам парламента, не занимающим официального поста класса в Деструкторе?

8
задан Mike Rosenblum 18 January 2010 в 22:36
поделиться

3 ответа

Вам бы пришлось отдать тело чистому виртуальному деструктору, например:)

Читайте: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/

(Ссылка разорвана, использовать архив)

-121--62360-

Я думаю, идея в том, что здесь WindowListener - вы можете добавить туда любой код, который вы хотели бы запустить, прежде чем вещь закроется

-121--776948-

Ближе всего .NET к деструктору, это то, что .NET называет завершителем. Основное отличие состоит в том, что деструктор обычно имеет детерминированную финализацию (скажем, когда отсчет ссылок на объект становится нулевым), в то время как финализатор .NET вызывается в неопределенное время после того, как на объект больше не ссылаются. Это выполняется сборщиком мусора .NET с помощью процедуры трассировки корней, а не простого подсчета ссылок.

Одна из лучших статей по этому вопросу - Сбор мусора: автоматическое управление памятью в Microsoft .NET Framework . Дополнительные сведения о финализаторах см. в статье Завершение методов и деструкторов в MSDN.

Не удается получить доступ к классу private члены в Destructor?

Нет, вы не можете сделать это безопасно.

В вашем случае происходит то, что когда на ваш объект больше нет прямой или косвенной ссылки со стороны корня, на COM-объекты, на которые ссылается ваш объект, т.е. на объекты, на которые ссылаются ваши частные поля, также не ссылается и корень. (Ссылка на эти COM-объекты в полях объекта не сохраняет их работоспособность, поскольку на ваш объект больше не ссылаются или не отслеживаются из корня, и, следовательно, COM-объекты не отслеживаются из корня.) Таким образом, ваш объект и все COM-объекты, на которые он ссылается, готовы к одновременному сбору мусора . Некоторое время спустя сборщик мусора очистит объект и вызовет его финализатор, как и COM-объекты, каждый из которых действительно является Runtime Callable Wrapper (RCW) .

Проблема в том, что не только время, когда эти объекты должны быть собраны мусором, является неопределенным, но и порядок , в котором называются финализаторы, также недетерминирован. В этом случае вызываемая оболочка среды выполнения также имеет финализатор, который вызывает Marshal.ReleaseComObject на себе, что приводит к уменьшению количества ссылок на COM-стороне ограждения, так что этот COM-объект может быть освобожден. Но поскольку порядок, в котором вызываются финализаторы, является неопределенным, вполне возможно, что финализаторы для COM-объектов, на которые ссылается объект, будут запускаться до финализатора для объекта. Так что код в финализаторе может работать иногда, но в большинстве случаев одна или несколько вызываемых оболочек среды выполнения, на которые уже будут ссылаться ваши объекты, будут вызваны их финализаторы, и базовый COM-объект будет выпущен,прежде чем финализатор выполнит свой код.

Короче говоря, следует избегать использования финализаторов в целом и никогда не обращаться к типам ссылок из финализатора, поскольку эти типы ссылок, возможно, уже были завершены.

Чтобы исправить вашу ситуацию, я бы рассмотрел две различные возможности:

  1. Утилизировать COM-объекты в рамках того же метода, который их создает. У меня есть пара обсуждений по этому здесь и здесь .

  2. Разрешите детерминированное удаление объекта, используя интерфейс IDisposable , вместо того, чтобы полагаться на недетерминированный финализатор.

Статьи о том, как реализовать образец IDisposable, см. в разделе

- Майк

16
ответ дан 5 December 2019 в 10:03
поделиться

Нет, вы не должны доходить к любым управляемым объектам в деструкторе: это включает в себя COM RCWS.

Вместо этого реализуйте стандартную idisposable Pattern и отпустите свои объекты COM в методе Dispose (Bool), подобном вам одноразовым управляющим объектом.

0
ответ дан 5 December 2019 в 10:03
поделиться

Я не уверен, что я кодирую что-то не так - пытался следовать примерам здесь. Я обнаружил, что когда я пользуюсь преимуществами idisposable Pattern, все работает, если мне не нужно обрабатывать события для рабочей книги.

В моем сценарии пользователь может закрыть рабочую книгу, прежде чем они закрывают приложение. Я объявил Excel Object Consevents и закодировал обработчик WorkbookBeforeSeClose для удовлетворения требований.

В этом сценарии я получаю «объект COM, который был разделен от его базового RCW, не может быть использован» ошибка при закрытии моего приложения (и я уже закрыл Excel). Ошибка происходит в доработки, когда он вызовет утилизировать (false).

Проблема уходит, если я оставлю объект Excel, объявленный с событиями, но не код каких-либо обработчиков.

В моем распоряжении мне пришлось проглотить ошибку для моих рабочих книг. Влоть и выйти, поскольку они были утверждениями, которые вызвали ошибку.

1
ответ дан 5 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: