2011-02-23 3 views
11

저는 C# 및 DirectShow.Net을 사용하여 디지털 TV (DVB-T)를 재생하기위한 일부 DirectShow 인터페이스로 작업 해 왔습니다. _guideData = _transportInformationFilter as IGuideData;C#에서 COM을 통해 쿼리 된 인터페이스에서 Marshal.ReleaseComObject를 호출해야하는 경우

_transportInformationFilter

유형의 IBaseFilter, 이전에 DirectShow.Net 유틸리티 기능을 통해 할당 된 COM 개체이다 : 나는 최근에이 오류는 다음 줄에 발생한 런타임 오류 COM object that has been separated from its underlying RCW cannot be used.

가 발생했습니다.

저는 오류로 인해 _transportInformationFilter 든 조기 릴리스되고 있었던 것으로 가정하고, I는 (에러가 제거 핸들링) 이하의 방법으로 추적 : 그것을 알 수 있듯이

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); 
    } 
} 

connPointContainer = _transportInformationFilter as IConnectionPointContainer 통화시킬 수도 ~ QueryInterface (_transportInformationFilter) COM 개체이므로 별도로 릴리스해야합니다. 그러나 Marshal.ReleaseComObject(connPointContainer)을 호출하면 _transportInformationFilter이 RCW와 분리됩니다. 이 전화를 끊으면 문제가 해결되었습니다.

주어진이 상황에서 어떤 경우에 리소스가 누출되지 않도록 C#에서 명시 적으로 COM 개체 (Marshal.ReleaseComObject 사용)를 릴리스해야합니까?

답변

10

거의 없습니다. ReleaseComObject는 기본 객체가 아닌 RCW의 참조 카운트를 관리하며 IUnknown.Release과 직접적으로 유사하지 않습니다. CLR이 QueryInterfaceRelease을 관리하도록해야합니다.

RCW에는 COM 인터페이스 포인터가 매핑 될 때마다 증가되는 참조 횟수가 있습니다. ReleaseComObject 메서드는 RCW의 참조 횟수를 감소시킵니다. 참조 횟수가 0이되면 런타임은 관리되지 않는 COM 개체에 대한 참조를 모두 해제하고 개체를 추가로 사용하려고 시도하면 System.NullReferenceException을 throw합니다. 동일한 COM 인터페이스가 관리되지 않는 코드에서 관리되는 코드로 두 번 이상 전달되면 래퍼의 참조 횟수가 매번 증가하고 ReleaseComObject를 호출하면 나머지 참조 수가 반환됩니다.

은 ...

이 방법은 사용자가 원하는 때 정확하게 이루어 지도록 당신이 RCW 참조 횟수 자료를 강제 할 수 있습니다. 그러나 ReleaseComObject를 부적절하게 사용하면 응용 프로그램이 실패하거나 액세스 위반이 발생할 수 있습니다. 참고로, 방법은 IUnknown.Release를 호출하는 http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx

에서

직접 Marshal.Release하지 ReleaseComObject입니다.

+0

정보 주셔서 감사합니다. MSDN 문서에서 호출자가 반환 된 인터페이스 (예 : http://msdn.microsoft.com/en-us/library/ms692476(VS.85).aspx)를 릴리스 할 책임이 있다고 말하면 런타임에서 호출을 관리합니다 객체가 범위를 벗어나거나 ReleaseComObject를 사용해야하는 상황이되면 나를 위해 출시 할 것인가? – jeffora

+0

개체가 "범위를 벗어 났을 때"작동하지만 RCW의 종료자가 실행될 때 작동하지 않으므로 connPoint의 경우에는 해를 끼치 지 않습니다. 중요한 점은'ReleaseComObject'가 RCW에서 작동한다는 것입니다.'Dispose'를 호출하는 것과 비슷하며,'a = _member as IFoo; a.Dispose(); _member.DoSomething()'이 (가) 중단 될 수 있습니다. –

+0

의견을 보내 주셔서 감사합니다. – jeffora

2

Marshal.ReleaseComObject를 사용하여 진정으로 합법적 인 환경을 발견했다고 생각합니다. ExcelDNA를 사용하여 C#에서 Excel Addins를 작성하면 작업자 스레드에서 COM interop를 사용하고 "Application", "Workbook"등과 같은 자동화 개체를 액세스하는 경향이 있습니다.

가비지 수집기가 이러한 개체를 마무리 할 때까지 기다린 경우 사용자가 종료 한 후에 작업 관리자에 남아있는 보이지 않는 Excel "좀비"인스턴스가 있습니다. RCW가 계속 살아 있기 때문에 그들은 꽤 오랫동안 달리기를 유지할 수 있기 때문입니다.

관련 문제