【发布时间】:2014-12-09 10:18:33
【问题描述】:
我不太擅长管理 COM 对象。我已经阅读了相当多的内容,但我无法完全理解当您有两个引用指向一个 COM 对象并释放其中一个时会发生什么。考虑以下[半]假设:
我用 C# 为 Excel 工作簿创建了一个基本的包装类:
using ExcelInterop = Microsoft.Office.Interop.Excel;
...
public class WorkbookWrapper : IDisposable
{
protected internal ExcelInterop.Workbook _wb;
public WorkbookWrapper(ExcelInterop.Workbook workbook)
{
_wb = workbook;
}
public WorkbookWrapper(WorkbookWrapper workbookWrapper)
{
_wb = workbookWrapper._wb;
}
#region IDisposable
// basic Dispose function which releases _wb COM Object (omitted to shorten post length)
#endregion
...
}
对于我正在进行的一个特定项目,我发现有必要将一些附加信息附加到 WorkbookWrapper 对象,因此我对其进行了扩展:
class LinkingWorkbookWrapper : WorkbookWrapper
{
internal string workbookGUID = null;
internal LinkingWorkbookWrapper(WorkbookWrapper workbookWrapper, string GUID) : base(workbook)
{
workbookGUID = GUID;
}
...
}
这个特定的类使用WorkbookWrapper(WorkbookWrapper) 构造函数来存储对互操作工作簿的新引用,这在使用如下函数时突然出现问题:
public static void ProcessAllCharts(WorkbookWrapper wbw)
{
LinkingWorkbookWrapper lwbw = null;
if(wbw is LinkingWorkbookWrapper)
lwbw = (LinkingWorkbookWrapper)wbw;
else
lwbw = new LinkingWorkbookWrapper(wbw, GenerateGUID());
//... do stuff ...
}
现在假设函数必须接受正常的WorkbookWrappers。 什么时候处理 lwbw 合适? 如果我在 ProcessAllCharts 结束时这样做,我可能会分离原始 wbw 中引用的 COM 对象来自其 RCW;另一方面,如果我不处理 lwbw,我会冒着将 COM 对象的引用留在以太中的风险。
【问题讨论】:
-
你可以使用析构函数。
-
@IllidanS4 由于析构函数(如果我理解正确的话)将在包装器上,那不会产生大致相同的效果吗?包装器在
ProcessAllCharts末尾超出范围,此时即使它的成员仍然从其他地方引用,它也有资格进行垃圾收集。再说一次,我对这类事情不是很有信心,所以我可能完全错了,但(到目前为止)这是我的理解。 -
叹息,让程序员摆脱困境是一项永无止境的艰巨任务。阅读this post,了解您认为需要这样做的原因。不要这样做,你永远不会做对。
-
好吧,所以我认为最好只有一个密封的包装类来跟踪一个 COM 对象。然后根本不要在 ProcessAllCharts 的 and 处调用 Dispose,以确保该对象仍然可以在方法范围之外使用。
-
@IllidanS4 我有点担心我的例子的答案是“你不能真的那样做”。 =(