2

我有一个问题可能对我来说太具体了,无法在这里获得任何帮助,但我想我会尝试的。我已经使用放置在我的 UI 中的 COM 对象创建了一个 ActiveX 连接。包装器实现 AxHost。我遇到的问题是,当我关闭 COM 对象所在的视图,然后尝试重新打开它时,我无法登录。

我是 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 对象已初始化的通知。但是,如果我尝试登录,我会收到一个错误代码,指出它未初始化。

有没有人对我可能犯的任何明显(或不那么明显)的错误有想法?如果有帮助,我很乐意提供更多信息。

4

2 回答 2

1

据我所知,您正在正确地收集对象。我唯一能建议的是使用 C++/CLI 作为包装器。这样,您就不会对 COM 对象使用 RCW(运行时可调用包装器),而是直接使用 COM 对象。您可以直接调用 IUnknown::Release。但我不确定多次调用 IUnknown::Release 直到引用计数为 0(如 FinalReleaseComObject)是否是个好主意。如果必须这样做,则意味着某些代码忘记了释放对象(内存泄漏),使用 FinalReleaseComObject 是解决问题的糟糕方法。

您的 Initialized 属性也可能有问题,但我对此一无所知。

于 2012-09-22T00:21:54.223 回答
0

根据我的经验(虽然从前一段时间),如果你真的想摆脱所有挥之不去的对象,你必须调用 GC.collect() 两次。

于 2014-05-25T11:49:08.023 回答