2015-03-25 2 views
0

У меня есть COM-объект:Как освободить COM-объект с IConnectionPointContainer и IConnectionPoints правильно

_myObject = (IMyInterface)Activator.CreateInstance(...); 

я могу получить IConnectionPointContainer:

_cpc = (IConnectionPointContainer)_myObject; 

И получить мою IConnectionPoint из этого:

IConnectionPoint _cp; 
_cpc.FindConnectionPoint(typeof(IMyCPInterface).GUID, out _cp); 
_cp.Advise(this, out _cookie); 

Я не уверен насчет правильного способа освобождения всех ресурсов сейчас. Как правильно освободить все созданные ресурсы?

На данный момент я это сделать, как показано ниже, но я не уверен, если я освободить все правильно:

protected virtual void Dispose(bool pDisposing) 
{ 
    if(!_isDisposed) 
    { 
    if(pDisposing) 
    { 
     //dispose managed 
    } 

    if(_cookie > 0 && _cp != null) 
    { 
     _cp.Unadvise(_cookie); 
     _cp = null;   //<-- ReleaseComObject(_cp); ? 
     _cookie = 0; 
    } 

    //I don't release _cpc, because it is the same object as _myObject? 

    if(_myObject != null) 
    { 
     Marshal.ReleaseComObject(_myObject); 
     _myObject = null; 
    } 

    _isDisposed = true; 
    } 
} 
+1

В общем: Release, как много раз в количество ссылок увеличивается. Т.е.: при запросе интерфейса (путем каста вроде: ((IConnectionPointContainer) _myObject), вы должны прочитать документ, чтобы определить, увеличивается ли количество ссылок (оно обычно есть). Marshal.FinalReleaseComObject может помочь: https: // msdn .microsoft.com/en-us/library/system.runtime.interopservices.marshal.finalreleasecomobject% 28v = vs.100% 29.aspx – Stefan

+0

Согласно: https://msdn.microsoft.com/en-us/library/ windows/desktop/ms692476% 28v = vs.85% 29.aspx, _cp должен быть выпущен. _cpc также должен быть выпущен, и, конечно же, должен также быть выпущен _myObject, возможно, дважды из-за нажатия IMyInterface. – Stefan

+0

Вы всегда можете его протестировать , ref-count должно быть 0, когда вы закончите с объектом. – Stefan

ответ

1

Резюмируя комментарии: это должно привести в надлежащее disposure СМИД объект:

protected virtual void Dispose(bool pDisposing) 
{ 
    if(!_isDisposed) 
    { 
     if(pDisposing) //dispose managed 
     { 
      if(_cookie > 0 && _cp != null) 
      { 
       _cp.Unadvise(_cookie); 
       _cookie = 0; 
      } 
      if (_cp != null) 
      { 
       Marshal.ReleaseComObject(_cp); 
       _cp = null;  
      } 
      if(_cpc != null) 
      { 
       //needed due to the implicit queryinterface on cast 
       //_cpc = (IConnectionPointContainer)_myObject; 
       Marshal.ReleaseComObject(_cpc); 
       _cpc = null; 
      } 
      if(_myObject != null) 
      { 
       //you could test if Marshal.ReleaseComObject(_myObject) == 0 
       //If it's not, the IMyInterface cast is probably increasing the refcount. 
       //but use FinalRelease just to be safe. 
       Marshal.FinalReleaseComObject(_myObject); 
       _myObject = null; 
      } 
     } 
     _isDisposed = true; 
    } 
} 

_cpc.FindConnectionPoint(typeof(IMyCPInterface).GUID, out _cp); будет увеличивать реф-счета:

Если вызов Succ essful, вызывающий отвечает за освобождение точки подключения, вызывая Release, когда точка подключения больше не нужна.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms692476%28v=vs.85%29.aspx

Метод FinalReleaseComObject:

Метод FinalReleaseComObject выпускает управляемую ссылку на объект СОМ. Вызов этого метода эквивалентен вызову метода ReleaseComObject в цикле, пока он не вернет 0 (ноль).

https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.finalreleasecomobject%28v=vs.100%29.aspx

Дополнительное примечание:

Хотя запрашивая интерфейсы объекта может привести к возвращая тот же объект, а иногда даже и то же значение указателя, вызов ReleaseComObject еще законным. Это происходит из-за внутреннего реф-графа, который может спровоцировать очистку объекта, если он попадает 0.

Более подробную информацию об управляемом RCW и COM:

https://msdn.microsoft.com/en-us/library/8bwh56xe%28v=vs.110%29.aspx

+2

Ничего из этого не требуется.Использование 'ReleaseComObject' должно ** ** использоваться ** только в тех случаях, когда вы не можете дождаться сбора мусора для завершения RCW, а' FinalReleaseComObject' должен ** ** ** использоваться, когда вы уверены, что хотите для отсоединения каждого RCW от базового COM-объекта. – acelent

+1

@PauloMadeira: хороший пункт там. Я раскрою этот термин. Хотя я думаю, что его хорошая привычка выпускать COM-объекты, особенно когда они создаются очень часто. – Stefan

+2

Это зависит от того, является ли объект, освобождающий COM-объект (с управляемой точки зрения) единственным его владельцем. Обычно объекты, которые создаются очень часто, попадают в этот случай, но не обязательно. Например. если вы повторяете листы Excel или ячейки, если вы не уверены, что управляемый код может содержать ссылку на один из них, вы должны использовать '* ReleaseComObject', вместо этого вы должны полагаться (возможно, принудительно, периодически или на спрос) сбор мусора. – acelent

 Смежные вопросы

  • Нет связанных вопросов^_^