COM组件的生命期控制

来源:互联网 发布:淘宝买dota账号 编辑:程序博客网 时间:2024/06/12 18:56
一、提供生命期控制函数的必要性。到目前为止客户对COM组件知道的仅仅是接口,因此客户也就不能直接控制组件的生命周期。为了客户能够更好的控制组件的生命周期,COM组件提供了一种直接控制单个接口生命周期来间接控制组件生命周期的方法。二、生命期控制。1、客户不直接控制组件生命期的原因。在客户的代码中,可能会有若干个指向此组件接口的指针。例如:客户的一部分通过一个指针使用组件的IX接口,另一部分通过另一个指针使用组件的IY接口,当不在使用IX接口时,可能还在使用IY接口。在这种情况下,当使用完一个接口时另一个接口可能还在被使用,因此组件是不能被释放的。这就很难决定何时释放掉组件。COM组件采用的方法是,由COM组件提供对每个接口的引用计数控制,即IUnknown接口的AddRef和Release函数。客户通过调用AddRef告诉组件开始使用这个接口,调用Release告诉组件使用完此接口。然后由组件自己决定是否释放组件。2、COM组件使用接口级引用计数与使用组件级引用计数。在用户来看,引用计数处于接口级而不是组件级的原因如下:<1>、方便调试 用户对接口操作时,很容易忘记调用Release函数,这就导致组件不能被释放掉。若采用组件级的应用计数,查找的范围是组件的所有接口;若采用接口级别引用计数查找的范围只需要限制在某个接口。从查找范围上来看采用接口级引用技术能够缩小需要调试的范围。<2>、资源按需获取 在实现一个接口时可能需要大量的内存和资源。若采用组件级的引用计数,只有当组件的所有接口都不再使用时,才能释放资源(包括早已不再使用的资源);若采用接口级的引用技术当接口不再使用时,此与次接口关联的资源就可以被释放。能够对不需要资源的及时释放,节省资源。三、引用计数规则。1、输出参数规则(即返回前调用AddRef规则)。任何在输出参数中或者作为返回值返回一个接口指针的函数必须对此接口调用AddRef。例如:HRESULT QueryInterface(const IID&, void**)在该函数返回前须调用AddRef。2、输入参数规则。对传入函数的指针,无需调用AddRef和Release,原因是函数的生命期嵌套在调用者的生命期内。例如:void FinalConstruct(IX* pIX){pIX->Fx();}3、输入-输出参数规则。对于用输入输出参数来传递进来的接口指针,必须在该指针给它赋另一个接口指针值之前调用其Release。这种情况类似与调用重载的赋值函数一样,需要先将就的资源释放掉,然后在给其赋予新的自愿。4、局部变量规则。对于局部复制的接口指针,由于它们是在函数的生命期内才存在,因此无需调用AddRef和Release。例如:void FinalConstruct(IX* pIX){ IX* pIX2 = pIX; pIX2->Fx();}5、全局变量规则。对于保存在全局变量中的接口指针,在将其传递给另外一个函数之前,必须调用AddRef,目的是防止在传入函数中调用Release从而终止该接口的生命期。例如:void FinalConstruct(IX* pIX){pIX->Release();}void main(){IX* pIX = NULL;HRESULT hr = QueryInterface(IID_IX, (void**)&pIX); if ( SUCCEED(hr) ){pIX->AddRef();FinalConstruct (pIX); pIX->Release();}}6、不能确定时的规则。当不确定该如何做时,需要调用AddRef和Release。总结:通过IUnknown接口QueryInterface、AddRef和Release函数的可以看出,IUnknown接口的这三个函数可以对接口进行完全控制。 QueryInterface函数用来查询组件支持的接口。 AddRef和Release函数用来控制接口的生命期,AddRef函数告诉组件客户要使用接口。Release告诉组件客户使用完了接口,可以从内存中释放该接口。
原创粉丝点击