ActiveX COM不释放所有对象

时间:2012-09-21 21:28:47

标签: c# com activex unmarshalling

我有一个问题可能对我来说太具体了,不能在这里得到任何帮助,但我想我会尝试。我已经创建了一个带有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对象已初始化的通知。但是,如果我尝试登录,则会收到一条错误代码,指出它未初始化。

有没有人对我可能犯过的任何明显(或不那么明显)的错误有所了解?如果它有用,我很乐意提供更多信息。

2 个答案:

答案 0 :(得分:1)

就我所见,你正确地垃圾收集对象。我唯一能建议的是使用C ++ / CLI作为包装器。这样就不会为COM对象使用RCW(Runtime Callable Wrapper),而是直接使用COM对象。你可以直接调用IUnknown :: Release。但我不确定多次调用IUnknown :: Release直到引用计数为0(如FinalReleaseComObject)。如果必须这样做,则意味着某些代码忘记释放对象(内存泄漏),并且使用FinalReleaseComObject是解决问题的一种不好的方法。

初始化属性中也可能存在错误,但我对此一无所知。

答案 1 :(得分:0)

根据我的经验(不久前),如果你真的想摆脱所有挥之不去的对象,你必须调用GC.collect()TWICE。