Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.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
C# 在事件运行后释放Inventor_C#_Com Interop_Autodesk_Autodesk Inventor - Fatal编程技术网

C# 在事件运行后释放Inventor

C# 在事件运行后释放Inventor,c#,com-interop,autodesk,autodesk-inventor,C#,Com Interop,Autodesk,Autodesk Inventor,该程序控制Autodesk Inventor,同时执行其应执行的操作,即压缩并将图形转换为所需的文件类型 程序运行后,我可以使用Inventor,但它不允许我保存任何内容,我认为程序仍然锁定了Inventor 我怎样才能释放它 如果你需要更多的信息,请告诉我 编辑#1 仅供参考,我没有编写此程序,而且我对Autodesk Vault/Inventor这一奇妙但令人困惑的世界一无所知 这就是我假设Inventor被C锁定的地方# 然后在函数末尾,m_inventorApp被设置为null m_in

该程序控制Autodesk Inventor,同时执行其应执行的操作,即压缩并将图形转换为所需的文件类型

程序运行后,我可以使用Inventor,但它不允许我保存任何内容,我认为程序仍然锁定了Inventor

我怎样才能释放它

如果你需要更多的信息,请告诉我

编辑#1

仅供参考,我没有编写此程序,而且我对Autodesk Vault/Inventor这一奇妙但令人困惑的世界一无所知

这就是我假设Inventor被C锁定的地方#

然后在函数末尾,m_inventorApp被设置为null

m_inventorApp = null;
m_inventorApp2 = null;

短版

您的代码根本没有释放COM引用。用于显式释放它,最好是在
try/finally
块中。也不要在字段中存储COM对象,尽可能晚地创建它们,并尽快释放它们,例如:

Inventor.Appication inventorApp=null;
try
{
    inventorApp = (Inventor.Application)Marshal.GetActiveObject("Inventor.Application");
    .....
}
finally
{
    if(inventorApp !=null)
    {
        Marshal.FinalReleaseComObject(inventorApp);
    }
}
使用
FinalReleaseComObject
而不是
ReleaseComObject
立即释放对象

将字段或变量设置为
null
仅意味着COM引用对象可用于垃圾收集,它不会减少COM的引用计数或显式释放COM对象

通过使用变量而不是字段,可以确保没有任何悬空引用

解释

您使用的是COM自动化,而不是Autodesk Inventor特有的东西。这是Windows上一个应用程序控制另一个应用程序的标准方式。COM早在.NET之前就构建了,它使用引用计数而不是垃圾收集。NET本身早在2000年就开始成为COM的“下一个”版本,直到2002年发布时才变得完全不同。COM是旧的

每次创建对COM对象的引用时,COM都会增加该对象的引用计数器。每次释放时,参考计数器都会递减。COM对象仅在计数器达到0时释放。这意味着您的代码必须确保计数器已递减,否则该对象将一直处于使用状态,直到垃圾收集器运行为止

.NET通过与COM组件一起工作。链接文档解释了引用计数、引用计数的工作原理以及释放引用所需的操作

调用时,您将获得对Inventor(或任何其他应用程序)已运行的COM server对象提供程序的引用。引用的计数器从1开始,并在每次创建新引用时增加

每个客户端应用程序都必须显式减少引用计数器。 COM服务器对象和创建它的应用程序在引用计数达到0之前无法关闭

为什么选择FinalReleaseComObject

当客户端请求对同一对象的多个引用时,它将使用递增的计数器返回同一引用。要真正释放一个对象,您必须释放该引用的次数与请求的次数相同。这导致Visual Basic 6和C++中有相当多的对象泄漏,尤其是当人们对引用不小心时。为了强制杀死一个对象,人们经常编写循环,在引用上反复调用
Release
,直到计数达到0

NET发布时,该方法只会将引用计数减少1。这导致VB6和C++具有相同的泄漏问题。当.NETFramework2.0在2005年问世时,它引入了
finalEleaseComObject
,实际上它本身就完成了循环。当涉及多个线程时,事情变得更加糟糕,这意味着一个线程可以释放COM对象,而另一个线程仍在使用它

文件现在解释说:

仅当绝对需要时才使用ReleaseComObject。如果要调用此方法以确保COM组件在确定的时间内释放,请考虑使用FielalRelaseCo对象方法。 FinalReleaseComObject将释放基础COM组件,无论其重新进入CLR的次数如何。每次COM组件重新进入CLR时,RCW的内部引用计数将增加1。因此,可以在循环中调用ReleaseComObject方法,直到返回的值为零。这将获得与FinalReleaseComObject方法相同的结果


您是否有可能导致此问题的代码示例?据我所知,在以编程方式调用autodesk后,可能有些东西没有正确地反初始化。@XouDo已更新。您的代码没有释放COM对象。简单地将变量设置为
null
不会释放任何内容。您需要在对象上调用
.Dispose()
,或者最好使用
using
块,而不是看起来像字段的块。这样,即使发生错误,COM对象也将被释放。顺便说一句,自20世纪90年代末以来,类型和成员前缀在所有编程语言中都是糟糕的形式。他们在C语言中使用了一些弱类型系统,但在较新的面向对象语言中没有,在这些语言中,所有的东西都是对象,类中的所有东西都是成员。COM ref计数器始终位于该对象的内部。COM对象的IUnknown::Release()(或AddRef)调用的返回值不应由任何人使用。任何人都不应该在发布时循环,这是错误的。FinalReleaseComObject不循环,它只是将RCW的计数器设置为0并释放它所持有的COM对象。ReleaseComObject只是减少该计数器,并且仅当RCW的计数器在此之后为0时才释放COM对象。我个人在COM对象上使用一次性包装器。请注意,即使所有引用都已消失,一些outofproc COM服务器仍能正常工作。
Inventor.Appication inventorApp=null;
try
{
    inventorApp = (Inventor.Application)Marshal.GetActiveObject("Inventor.Application");
    .....
}
finally
{
    if(inventorApp !=null)
    {
        Marshal.FinalReleaseComObject(inventorApp);
    }
}