我有一个问题可能对我来说太具体了,不能在这里得到任何帮助,但我想我会尝试。我已经创建了一个带有COM对象的ActiveX连接,该对象放在我的UI中。包装器实现了AxHost。我遇到的问题是,当我关闭COM对象所在的View,然后尝试重新打开它时,我无法登录。
我是ActiveX和COM的新手,但我发现我没有正确关闭所有对象。我已经阅读并尝试了几种解决方案,但它们似乎都没有用。目前,我已经重写了包装器Dispose方法,试图破坏连接,如下所示:
protected override void Dispose(bool disposing)
{
Marshal.FinalReleaseComObject(ocx);
base.Dispose(disposing);
}
据我所知,ocx是唯一创建的COM对象。在视图类中,我也试图摆脱对COM对象的所有引用,如下所示:
protected void FormClosing(object sender, FormClosingEventArgs e)
{
try
{
wrapper.CloseCanvasPage(canvasPageId, false);
IsLoggedIn = !wrapper.Logout();
wrapper.EndInit();
wrapper.Dispose();
wrapper = null;
// Garbage collect the unclosed ActiveX connections.
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex) { }
}
}
我意识到手动调用垃圾收集很糟糕,但是几个帖子说这会消除流浪连接。它似乎不起作用。
在父级中,我在视图上调用Dispose,并将其设置为null,尝试断开任何连接,但我仍然有一些问题。当我尝试创建一个新连接,并调用Initialized(我正在使用的包装器中包含的属性)时,我收到COM对象已初始化的通知。但是,如果我尝试登录,则会收到一条错误代码,指出它未初始化。
有没有人对我可能犯过的任何明显(或不那么明显)的错误有所了解?如果它有用,我很乐意提供更多信息。
答案 0 :(得分:1)
就我所见,你正确地垃圾收集对象。我唯一能建议的是使用C ++ / CLI作为包装器。这样就不会为COM对象使用RCW(Runtime Callable Wrapper),而是直接使用COM对象。你可以直接调用IUnknown :: Release。但我不确定多次调用IUnknown :: Release直到引用计数为0(如FinalReleaseComObject)。如果必须这样做,则意味着某些代码忘记释放对象(内存泄漏),并且使用FinalReleaseComObject是解决问题的一种不好的方法。
初始化属性中也可能存在错误,但我对此一无所知。
答案 1 :(得分:0)
根据我的经验(不久前),如果你真的想摆脱所有挥之不去的对象,你必须调用GC.collect()TWICE。