.NET强制COM对象发布
我在IIS下有一个ASP.NET 2.0应用程序,它的功能是 将一些数据导出到名为HFM Oracle Hyperion Financial Management的软件。 要执行该导出,.net应用程序使用基于HFM客户端提供的COM对象的API。客户端安装在服务器所在的同一台机器上,等等 我的问题是API提供了一种连接到HFM服务器但不断开连接的方法。 文档说明,要断开连接,应用程序必须对创建的每个COM对象调用Marshal.ReleaseComObject方法。 但是执行了很多复杂的操作,我无法释放所有创建的对象。 所以我的应用程序不会断开连接 我注意到,当我替换ASP.NET应用程序dll文件时,应用程序会自动断开连接,而ASP.NET应用程序dll文件似乎会重新生成由.NET实例化的对象 我试过几次打电话:.NET强制COM对象发布,.net,asp.net,com,.net,Asp.net,Com,我在IIS下有一个ASP.NET 2.0应用程序,它的功能是 将一些数据导出到名为HFM Oracle Hyperion Financial Management的软件。 要执行该导出,.net应用程序使用基于HFM客户端提供的COM对象的API。客户端安装在服务器所在的同一台机器上,等等 我的问题是API提供了一种连接到HFM服务器但不断开连接的方法。 文档说明,要断开连接,应用程序必须对创建的每个COM对象调用Marshal.ReleaseComObject方法。 但是执行了很多复杂的操作,
GC.Collect();
GC.WaitForPendingFinalizers();
但问题依然存在。
我正在寻找一种方法来确保创建的任何对象,甚至COM对象都被释放。
我试过Marshal.FinalEleaseComObject,但没有更好
当我锁定该部分时,该部分最多只有一个用户,因此我甚至可以使用核心技术来释放COM对象
有没有办法知道哪个对象或者至少是对象的类型没有被释放
谢谢您的帮助。能否在每个COM实例周围放置一个实现IDisposable的通用包装器类型 然后,您可以调用Marshal.FinalReleaseComObject或Marshal.ReleaseComObject上的循环来检查Dispose方法中的refcount,并且只能通过引用包装器类型的using语句实例化COM对象
使用此包装技巧的另一个好处是,您可以使用检查哪些类型实例尚未被处置,从而回答您的最后一个问题。能否在每个COM实例周围放置一个实现IDisposable的通用包装类型 然后,您可以调用Marshal.FinalReleaseComObject或Marshal.ReleaseComObject上的循环来检查Dispose方法中的refcount,并且只能通过引用包装器类型的using语句实例化COM对象 使用此包装技巧的另一个好处是,您可以使用检查哪些类型实例尚未被处置,从而回答最后一个问题 但是执行了很多复杂的操作,我无法释放所有创建的对象 这是你的问题 你在寻找一条简单的出路。但你在和COM合作。唯一简单的解决方法是关闭进程/appdomain 但是执行了很多复杂的操作,我无法释放所有创建的对象 这是你的问题
你在寻找一条简单的出路。但你在和COM合作。唯一简单的解决方法是关闭进程/appdomain。在调用Marshal.ReleaseComObject或Marshal.FinalReleaseComObject后,将变量设置为Null/Nothing是绝对重要的
Dim cn As ADODB.Connection
cn = New ADODB.Connection
cn.Open(_cnnstr)
cn.Execute(sbDML.ToString)
cn.Close()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cn)
cn = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!
此外,我注意到创建另一个方法有助于避免处理放置在堆栈上的本地COM对象变量时出现问题。例如,如果您有一个方法可以执行所有操作,请将其包装到另一个方法中,添加对垃圾收集的调用,然后调用包装器
Public Sub MainMethod
'...
Marshal.FinalReleaseComObject(foo)
foo = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!
End Sub
Public Sub WrapperMethod
Call MainMethod
GC.Collect()
End Sub
我相信额外的调用,为局部变量创建了一个附加堆栈,强制更快地完全收集对象,并导致COM对象完全释放
我已经遵循这种模式好几年了,从那以后我就没有遇到任何问题。在调用Marshal.ReleaseComObject或Marshal.FinalReleaseComObject后,将变量设置为Null/Nothing是绝对重要的
Dim cn As ADODB.Connection
cn = New ADODB.Connection
cn.Open(_cnnstr)
cn.Execute(sbDML.ToString)
cn.Close()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cn)
cn = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!
此外,我注意到创建另一个方法有助于避免处理放置在堆栈上的本地COM对象变量时出现问题。例如,如果您有一个方法可以执行所有操作,请将其包装到另一个方法中,添加对垃圾收集的调用,然后调用包装器
Public Sub MainMethod
'...
Marshal.FinalReleaseComObject(foo)
foo = Nothing '!!!IMPORTANT!!! - Do not remove, MUST be explicitly called!
End Sub
Public Sub WrapperMethod
Call MainMethod
GC.Collect()
End Sub
我相信额外的调用,为局部变量创建了一个附加堆栈,强制更快地完全收集对象,并导致COM对象完全释放
我已经遵循这种模式好几年了,从那以后我就没有遇到任何问题。你是对的,经过彻底的分析和过程简化,我们注意到一些对象没有正确释放。这就是问题的原因。你是对的,在经过彻底的分析和过程简化后,我们注意到一些对象没有被正确地释放。这就是问题的原因。