释放Excel对象在析构函数 [英] Release Excel Object In My Destructor

查看:206
本文介绍了释放Excel对象在析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在写使用Microsoft.Interropt.Excel DLL中的Excel的类。 我完成所有的功能,但我有我的析构函数的错误。 我要保存所有更改我的文件,我想释放所有的源代码。我想所有的人都在我的析构函数。 但在我的析构函数,Excel.ApplicationClass,工作簿和工作表对象填补了异常具有信息已被分开与其基础RCW不能使用COM对象。 所以,我救不了什么,靠近什么,因为我无法访问工作簿或工作表对象。

I'm writing a Excel class using Microsoft.Interropt.Excel DLL. I finish all function but I have an error in my Destructor. I Want to save all changes to my file and I want to release all source. I want to all of them in my destructor. But In my destructor, Excel.ApplicationClass, Workbook and Worksheet objects are fill by an Exception which have message "COM object that has been separated from its underlying RCW cannot be used." So I can't save nothing, close nothing because ı can't access workbook or worksheet object.

我不能访问在析构函数类的私有成员?

Can't I access the class private members in Destructor?

推荐答案

最近的事情,.NET有一个析构函数,是.NET调用终结。的主要区别在于,析构函数通常具有确定性终止(例如,当在对象上的引用计数变为零),而一个.NET终结处调用一个的未确定时间后的对象不再引用。这是通过使用一个根追踪的过程,而不是使用简单的引用计数的.NET垃圾收集处理。

The closest thing that .NET has to a destructor, is what .NET calls a finalizer. The main difference is that a destructor typically has deterministic finalization (say, when the reference count on the object becomes zero), while a .NET finalizer is called at an undetermined time after the object is no longer referenced. This is handled by the .NET Garbage Collector using a roots-tracing procedure, rather than using simple reference counting.

其中关于这一点的最好的文章是垃圾收集:在Microsoft .NET框架自动内存管理。欲了解更多关于终结具体地说,请参阅文章 finalize方法和析构函数的MSDN中

One of the best articles on this is Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework. For more on finalizers specifically, see the article Finalize Methods and Destructors in MSDN.

我不能访问类的私有   在析构函数的成员?

Can't I access the class private members in Destructor?

没有,你不能这样做安全。

No, you cannot do so safely.

什么是发生在你的情况是,当你的对象不再直接或间接引用的一个根时,COM对象,你的对象引用 - 也就是您的私有字段引用的对象 - 也没有引用由root身份。 (作为您的对象的字段引用它的没有的保持这些COM对象还活着,因为你的目标是不再被引用,或从根追踪,和,因此,COM对象不从根追踪无论是。)因此,你的对象,所有的COM对象的时候引用都愿意被垃圾收集的同时的。一段时间后,垃圾收集器将清理的对象,并调用它的终结,因为它也将做的COM对象,每一个都是一个真正的的Runtime可调用包装(RCW)

What is happening in your case is that when your object is no longer directly or indirectly referenced by a root, the COM objects that your object references -- that is, the objects referenced by your private fields -- are also not referenced by a root either. (Being reference by your object's fields does not keep these COM objects alive because your object is no longer referenced by, or traced from, a root, and, therefore, the COM objects do not trace from a root either.) So your object and all the COM objects it references are all ready to be garbage collected at the same time. Some time later, the garbage collector will cleanup your object and call its finalizer, as it will also do with the COM objects, each of which is really a Runtime Callable Wrapper (RCW).

麻烦的是,不光是定时到时这些对象进行垃圾回收不确定性,但订单的其中终结被称为也是不确定的。在这种情况下,运行时可调用包装也有一个终结,它调用<一href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx">Marshal.ReleaseComObject在其自身上,其中有递减的围栏上的COM侧的引用计数,使得此COM对象可以释放的结果。但是,由于在该终结调用的顺序是不确定的,它很可能是终结了终结为对象之前,COM对象,你的对象引用会火的。所以,你的终结中的code的可以的工作的时候,但是,大多数时候,一个或多个运行时可调用包装的,你的对象引用将已经有自己的终结叫,和底层COM对象将陆续公布,在你得到终结执行其code。

The trouble is that not only is the timing as to when these objects are to be garbage collected uncertain, but the order in which the finalizers are called is also nondeterministic. In this case, a Runtime Callable Wrapper also has a finalizer, which calls Marshal.ReleaseComObject on itself, which has the result of decrementing the reference count on the COM side of the fence so that this COM object can be released. But since the order in which the finalizers are called is uncertain, it is very possible that the finalizers for the COM objects that your object references will fire before the finalizer for your object. So the code within your finalizer could work sometimes, but, most of the time, one or more of the Runtime Callable Wrappers that your object references will have already had their finalizers called, and the underlying COM object will have been released, before your finalizer gets to execute its code.

总之,你应该避免使用终结一般,你永远不应该从一个终结内部访问引用类型,因为这些类型的引用可能已经完成。

In short, you should avoid using finalizers in general, and you should never access reference types from within a finalizer, because these reference types may have already been finalized.

要纠正你的情况,我会考虑两种可能:

To remedy your situation, I would consider two different possibilities:

  1. 处置创建它们的同一方法中的COM对象。我在这里和<一本一对夫妇的讨论href="http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c/159419#159419">here.

通过使用 IDisposable接口,而不是依靠非确定性终结。

Enable deterministic disposal of your object by making use of the IDisposable interface, instead of relying on the non-deterministic finalizer.

有关如何实现IDisposable模式文章,请参阅:

For articles on how to implement the IDisposable pattern, see:

迈克 -

这篇关于释放Excel对象在析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆