我正在开发一个VSTO插件,现在我正在寻找优化它。在我的代码中,我做了一些事情
public class ExtraOrdinaryClass
{
public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
{
tSheetName = someGoodSheet.Name;
tDesignSheet = someGoodSheet;
}
}
我只是知道我应该释放所有COM对象,但我正在寻找一种正确的方法来以正确的方式释放someGoodSheet
对象。我怀疑如果我做下面的事情是有效的
public class ExtraOrdinaryClass
{
public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
{
tSheetName = someGoodSheet.Name;
tDesignSheet = someGoodSheet;
Marshal.ReleaseComObject(someGoodSheet);
someGoodSheet = null;
}
}
如果我有效地执行此操作并且告诉我垃圾收集器何时收集参数对象,那么任何人都可以帮助我吗?
答案 0 :(得分:0)
我只是知道我应该释放所有的COM对象,但我正在寻找一种正确的方式以正确的方式释放someGoodSheet对象
由于您正在编写VSTO加载项,因此无需担心释放COM对象。 VSTO加载项是由COM应用程序加载的进程内 COM库,在本例中为Excel。 Excel工作表表示的COM对象是由Excel创建的,因此它具有所有权。尝试手动释放(通过Marshal.ReleaseComObject
)或在您仍然拥有托管引用时非常减少引用计数(如第二个示例中所示),可能会导致Excel和/或应用程序崩溃。
如果您正在编写一个独立的过程,即通过COM启动Excel并摆弄一些COM对象,然后是,则需要确保COM对象被正确释放。
即。 不在构造函数中使用它:
Marshal.ReleaseComObject(someGoodSheet);
因为你基本上是对COM"我已经完成了它"但你不是因为你仍然通过tDesignSheet
引用了一个托管。 COM / Excel可能会选择从您下面删除工作表。下次访问tDesignSheet
时,您可能会遇到异常。
在复制到字段的参数上调用Marshal.ReleaseComObject
有点像在调用Font
后使用Dispose()
- 这两种情况都会导致被删除的对象出现意外情况访问。 (在COM的情况下,我假设引用计数达到0)
没有必要来调用它(因为你无论如何都引用了同一个对象):
someGoodSheet = null;
您的原始代码(如下所示)很好:
public class ExtraOrdinaryClass
{
public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
{
tSheetName = someGoodSheet.Name; // you arguably don't need this (just read tDesignSheet.Name)
tDesignSheet = someGoodSheet;
}
}
告诉我什么时候垃圾收集器收集参数对象?
我想说在这种情况下,不会收集.NET参数,因为现在您在tDesignSheet
ExtraOrdinaryClass
内有一个额外的引用。您需要将tDesignSheet
设置为null
并等待GC下次运行,无论何时都是。
即使收集了.NET对象,我怀疑.NET足够聪明,知道COM对象可能仍然被其他本机COM客户端使用,例如Excel本身。
因此,仅仅因为您的.NET现在处理的对象不再引用COM对象,您可能会发现COM对象仍然可以处于活动状态。例如工作表仍然是开放的。