Я пишу использованию класса Excel Microsoft. Interropt. Excel DLL. Я заканчиваю всю функцию, но у меня есть ошибка в моем Деструкторе. Я Хочу сохранить все изменения в своем файле, и я хочу выпустить весь источник. Я хочу всем им в моем деструкторе. Но В моем деструкторе, Excel. ApplicationClass, Рабочая книга и объекты Рабочего листа являются заливкой Исключением, которые имеют сообщение "COM-объект, который был разделен от его базового RCW, не может использоваться". Таким образом, я ничего не могу сохранить, ничего не закрыть, потому что ı не может получить доступ к рабочей книге или объекту рабочего листа.
Разве я не могу получить доступ к членам парламента, не занимающим официального поста класса в Деструкторе?
Вам бы пришлось отдать тело чистому виртуальному деструктору, например:)
Читайте: 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-объект будет выпущен,прежде чем финализатор выполнит свой код.
Короче говоря, следует избегать использования финализаторов в целом и никогда не обращаться к типам ссылок из финализатора, поскольку эти типы ссылок, возможно, уже были завершены.
Чтобы исправить вашу ситуацию, я бы рассмотрел две различные возможности:
Утилизировать COM-объекты в рамках того же метода, который их создает. У меня есть пара обсуждений по этому здесь и здесь .
Разрешите детерминированное удаление объекта, используя интерфейс IDisposable , вместо того, чтобы полагаться на недетерминированный финализатор.
Статьи о том, как реализовать образец IDisposable, см. в разделе
- Майк
Нет, вы не должны доходить к любым управляемым объектам в деструкторе: это включает в себя COM RCWS.
Вместо этого реализуйте стандартную idisposable Pattern и отпустите свои объекты COM в методе Dispose (Bool), подобном вам одноразовым управляющим объектом.
Я не уверен, что я кодирую что-то не так - пытался следовать примерам здесь. Я обнаружил, что когда я пользуюсь преимуществами idisposable Pattern, все работает, если мне не нужно обрабатывать события для рабочей книги.
В моем сценарии пользователь может закрыть рабочую книгу, прежде чем они закрывают приложение. Я объявил Excel Object Consevents и закодировал обработчик WorkbookBeforeSeClose для удовлетворения требований.
В этом сценарии я получаю «объект COM, который был разделен от его базового RCW, не может быть использован» ошибка при закрытии моего приложения (и я уже закрыл Excel). Ошибка происходит в доработки, когда он вызовет утилизировать (false).
Проблема уходит, если я оставлю объект Excel, объявленный с событиями, но не код каких-либо обработчиков.
В моем распоряжении мне пришлось проглотить ошибку для моих рабочих книг. Влоть и выйти, поскольку они были утверждениями, которые вызвали ошибку.