如何使用 IConnectionPointContainer 和 IConnectionPoints 正确释放 COM 对象
How to free a COM Object with IConnectionPointContainer and IConnectionPoints properly
我有一个 COM 对象:
_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;
}
}
总结评论:这应该导致正确处置 COM 对象:
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);
将增加引用计数:
If the call is successful, the caller is responsible for releasing the connection point by calling Release when the connection point is no longer needed.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms692476%28v=vs.85%29.aspx
FinalReleaseComObject 方法:
The FinalReleaseComObject method releases the managed reference to a COM object. Calling this method is equivalent to calling the ReleaseComObject method in a loop until it returns 0 (zero).
补充说明:
虽然查询对象的接口可能会返回相同的对象,有时甚至是相同的指针值,但对 ReleaseComObject
的调用仍然是合法的。这是因为内部引用计数可以触发清理对象,如果它命中 0。
有关托管 RCW 和 COM 的更多信息:
https://msdn.microsoft.com/en-us/library/8bwh56xe%28v=vs.110%29.aspx
我有一个 COM 对象:
_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;
}
}
总结评论:这应该导致正确处置 COM 对象:
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);
将增加引用计数:
If the call is successful, the caller is responsible for releasing the connection point by calling Release when the connection point is no longer needed.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms692476%28v=vs.85%29.aspx
FinalReleaseComObject 方法:
The FinalReleaseComObject method releases the managed reference to a COM object. Calling this method is equivalent to calling the ReleaseComObject method in a loop until it returns 0 (zero).
补充说明:
虽然查询对象的接口可能会返回相同的对象,有时甚至是相同的指针值,但对 ReleaseComObject
的调用仍然是合法的。这是因为内部引用计数可以触发清理对象,如果它命中 0。
有关托管 RCW 和 COM 的更多信息:
https://msdn.microsoft.com/en-us/library/8bwh56xe%28v=vs.110%29.aspx