Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.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# 什么时候我需要在C中通过COM查询的接口上调用Marshal.ReleaseComObject#_C#_Com_Interop - Fatal编程技术网

C# 什么时候我需要在C中通过COM查询的接口上调用Marshal.ReleaseComObject#

C# 什么时候我需要在C中通过COM查询的接口上调用Marshal.ReleaseComObject#,c#,com,interop,C#,Com,Interop,我一直在使用一些DirectShow接口,使用C#和。我最近遇到运行时错误COM对象,该对象已与其基础RCW分离,无法使用。 此错误发生在以下行中: \u guideData=\u transportInformationFilter作为IGuideData \u transportInformationFilter属于IBaseFilter类型,是以前通过DirectShow.Net实用程序函数分配的COM对象 我假设该错误是由于\u transportInformationFilter提前发

我一直在使用一些DirectShow接口,使用C#和。我最近遇到运行时错误
COM对象,该对象已与其基础RCW分离,无法使用。

此错误发生在以下行中:

\u guideData=\u transportInformationFilter作为IGuideData

\u transportInformationFilter
属于IBaseFilter类型,是以前通过DirectShow.Net实用程序函数分配的COM对象

我假设该错误是由于
\u transportInformationFilter
提前发布造成的,我将其追溯到以下方法(已删除错误处理):

据我所知,
connPointContainer=\u transportInformationFilter As IConnectionPointContainer
应该导致调用
\u transportInformationFilter
COM对象上的
QueryInterface
,因此需要单独释放。但是,调用
封送.ReleaseComObject(connPointContainer)
是导致
\u transportInformationFilter
与其RCW分离的罪魁祸首;删除此呼叫修复了此问题


鉴于此,在什么情况下,我需要在C#中显式释放COM对象(使用
Marshal.ReleaseComObject
),以避免资源泄漏?
几乎从不。ReleaseComObject管理RCW的引用计数,而不是底层对象,并且与IUnknown.Release不直接类似。您应该让CLR管理其
查询接口
'ing和
发布
'ing

RCW有一个引用计数,每次COM接口指针映射到它时,该计数都会递增。ReleaseComObject方法减少RCW的引用计数。当引用计数达到零时,运行时将释放非托管COM对象上的所有引用,如果您试图进一步使用该对象,则会抛出System.NullReferenceException。如果同一COM接口多次从非托管代码传递到托管代码,则包装上的引用计数每次都会增加,并且调用ReleaseComObject将返回剩余引用的数量

此方法使您能够强制释放RCW引用计数,以便它在您希望的时候准确地发生。但是,不正确使用ReleaseComObject可能会导致应用程序失败,或者导致访问冲突


仅供参考,直接调用
IUnknown.Release
的方法是,而不是
ReleaseComObject

我想我已经找到了使用Marshal.ReleaseComObject的真正合法的环境。使用ExcelDNA在C#中编写excel加载项时,我倾向于从工作线程使用COM互操作,并访问excel自动化对象,如“应用程序”、“工作簿”等


如果我等待垃圾收集器完成这些对象,那么在用户退出excel后,任务管理器中会有一个不可见的excel“僵尸”实例。这是因为这些RCW保持了excel的活力,它们可以在相当长的一段时间内保持运行。

感谢您提供的信息。如果MSDN文档说调用方专门负责释放返回的接口(例如),那么运行时是否会在对象超出范围时为我管理释放调用,或者我应该使用ReleaseComObject?当对象“超出范围”时,它不会运行但是,当RCW的终结器运行时,对于connPoint的情况,它不会有任何影响。需要记住的重要一点是,
ReleaseComObject
在RCW上运行,它就像调用
Dispose
,并且由于与IFoo类似的原因而中断;a、 处置()_member.DoSomething()
可能会崩溃。非常感谢您的反馈,这很有意义。@Logan:您是否有一些关于“几乎从未”的参考资料似乎我的同事无法忍受这种不确定性(他是.NET新手)@Daniel这个答案可以写得更清楚。如果您试图管理COM对象的引用计数(AddRef/Release),则不应这样做,如果您希望确定地释放COM对象,则最有可能使用FinalReleaseComObject。参考资料几乎就是我一直链接到的ReleaseComObject的文档。“…因此,仅当绝对需要时才使用ReleaseComObject。”
private void AttachGuideDataEvent()
{
    IConnectionPoint connPoint = null;
    IConnectionPointContainer connPointContainer = null;
    try
    {
        connPointContainer = _transportInformationFilter as IConnectionPointContainer;
        if (connPointContainer == null) /* error */

        var guideDataEventGuid = typeof (IGuideDataEvent).GUID;
        connPointContainer.FindConnectionPoint(ref guideDataEventGuid, out connPoint);
        if (connPoint == null) /* error */

        int cookie;
        connPoint.Advise(this, out cookie);
        if (cookie == 0) /* error */    
        _persistIGuideDataEventCookie = cookie;
    }
    finally
    {
        if (connPointContainer != null)
            Marshal.ReleaseComObject(connPointContainer);
        if (connPoint != null)
            Marshal.ReleaseComObject(connPoint);
    }
}