Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET强制COM对象发布_.net_Asp.net_Com - Fatal编程技术网

.NET强制COM对象发布

.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方法。 但是执行了很多复杂的操作,

我在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实例化的对象

我试过几次打电话:

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对象完全释放


我已经遵循这种模式好几年了,从那以后我就没有遇到任何问题。

你是对的,经过彻底的分析和过程简化,我们注意到一些对象没有正确释放。这就是问题的原因。你是对的,在经过彻底的分析和过程简化后,我们注意到一些对象没有被正确地释放。这就是问题的原因。