我一直在使用一些DirectShow接口来使用C#和DirectShow.Net播放数字电视(DVB-T).我最近遇到了运行时错误COM object that has been separated from its underlying RCW cannot be used.
此错误发生在以下行:
_guideData = _transportInformationFilter as IGuideData;
_transportInformationFilter 是IBaseFilter类型,是以前通过DirectShow.Net实用程序函数分配的COM对象.
我认为错误是由于_transportInformationFilter某种程度上过早释放,我跟踪它到以下方法(删除错误处理):
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);
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,connPointContainer = _transportInformationFilter as IConnectionPointContainer应该导致QueryInterface对_transportInformationFilterCOM对象的调用,因此需要单独发布.然而,呼吁Marshal.ReleaseComObject(connPointContainer)是导致_transportInformationFilter与RCW分离的罪魁祸首; 删除此调用修复了该问题.
鉴于此,在什么情况下我需要Marshal.ReleaseComObject在C#中显式释放COM对象(使用)以避免泄漏资源?
Log*_*ldo 11
几乎从不.ReleaseComObject管理RCW的引用计数,而不是底层对象,并且不直接类似于IUnknown.Release.你应该让CLR管理它的QueryInterface'ing Release' 和ing ing.
RCW的引用计数在每次COM接口指针映射到它时递增.ReleaseComObject方法减少RCW的引用计数.当引用计数达到零时,运行时将释放其对非托管COM对象的所有引用,如果您尝试进一步使用该对象,则抛出System.NullReferenceException.如果从非托管代码到托管代码多次传递相同的COM接口,则包装器上的引用计数每次递增,并且调用ReleaseComObject将返回剩余引用的数量.
...
此方法使您可以强制RCW引用计数释放,以便在您需要时准确发生.但是,不恰当地使用ReleaseComObject可能会导致应用程序失败,或者可能导致访问冲突.
来自http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx
仅供参考,IUnknown.Release直接打电话的方式Marshal.Release不是ReleaseComObject.
我想我已经找到了使用Marshal.ReleaseComObject的真正合法的情况。使用ExcelDNA在C#中编写excel插件时,我倾向于从工作线程使用COM互操作,并访问excel自动化对象,例如“应用程序”,“工作簿”等。
如果我等待垃圾收集器完成这些对象的处理,那么在用户退出excel之后,任务管理器中将保留一个不可见的excel“僵尸”实例。这是因为这些RCW可以保持卓越的性能,并且可以保持运行相当长的时间。
| 归档时间: |
|
| 查看次数: |
13724 次 |
| 最近记录: |