0

I am developing a VSTO addin where now I am looking to optimize it. In my code, I does something

public class ExtraOrdinaryClass
{
    public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
    {
        tSheetName            = someGoodSheet.Name;
        tDesignSheet          = someGoodSheet;
    }
}

I just got to know I should release all the COM Objects, but I am searching for a proper way to release the someGoodSheet object in a proper way. I suspect if I do something like below is efficient

public class ExtraOrdinaryClass
{
    public ExtraOrdinaryClass(Excel.Worksheet someGoodSheet)
    {
        tSheetName            = someGoodSheet.Name;
        tDesignSheet          = someGoodSheet;
        Marshal.ReleaseComObject(someGoodSheet);
        someGoodSheet = null;
    }
}

Can anyone help me if I am doing it effectively and tell me when parameter objects are collected by garbage collector?

4

1 回答 1

0

我刚刚知道我应该释放所有 COM 对象,但我正在寻找一种适当的方法来以适当的方式释放 someGoodSheet 对象

不必担心释放 COM 对象,因为您正在编写 VSTO 加载项。VSTO 加载项是由 COM 应用程序(在本例中为 Excel)加载的进程内COM 库。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 参数,因为现在您在tDesignSheetinside中有一个额外的引用ExtraOrdinaryClass。无论何时,您都需要设置tDesignSheetnull并等待 GC 下次运行。

即使收集了 .NET 对象,我怀疑 .NET 足够聪明,可以知道 COM 对象仍可能被其他本机 COM 客户端(例如 Excel 本身)使用。

因此,仅仅因为您的 .NET 现在处理的对象不再引用 COM 对象,您可能会发现 COM 对象很可能仍然处于活动状态。例如,工作表仍然打开。

于 2015-11-17T05:34:03.707 回答