RPC_S_SERVER_UNAVAILABLE (0x800706ba) this means Remote Server unavailable!! so you must try to catch all com error, your application must exit normally when you application catch the error,becuse maybe the event server is terminated unconditionally.
to phiger 难道这是唯一的解决办法吗?还有没有更好的办法?与我要实现的功能类似的一个程序就没有出现我所遇到的问题,但是我没搞懂。
你应该确定服务器在客户Unadvise之前不能被关闭
so you must try to catch all com error, your application must exit normally when you application catch the error,becuse maybe the event server is terminated unconditionally.
难道这是唯一的解决办法吗?还有没有更好的办法?与我要实现的功能类似的一个程序就没有出现我所遇到的问题,但是我没搞懂。
如果服务器突然死亡,对连接点客户端的调用无法释放,所以你的组件也不能释放。解决的办法是连接点客户端的实现不能采用普通的IUnknown实现(即CComObject的实现),然它的AddRef()以及Release()什么都不做,例如,ATL::IDispEventImpl就是这样做的。
如果你从一般的ATL Class中派生自事件接口,肯定是不行的,因为最终的子类是CComObject,它的AddRef(),Release()会覆盖子类的实现。较好的办法是把Sink对象作为一个单独的对象,并且它的AddRef(),Release()什么也不做,然后它跟客户端的其它对象可以用指针来联系。
正如你说的,在我所看的另一个代码中确实是做了一个影子组件S实现sink 接口,然后在真实组件R中实现同样的sink 接口,R中定义了一个S实例:CComObject<S> m_Shadow,S同时实现了另一个接口Ib用于与R通信,S中会保留一个sink 接口指针m_pSinkR,在消息响应函数中调用m_pSinkR对应的函数。R在初始化时会将自己的sink 接口通过Ib接口传给S实例m_Shadow,然后把所有要注册的事件都统统注册到 m_Shadow 上,这样当收到消息时 m_Shadow 会将消息转发给R的实例,由R的实例真正处理事件。这就与你所说的把 Sink对象作为一个单独的对象差不多,但是R中创建S实例时所用的 CComObject<S> 方法仍然会增加引用计数是吗?另外如果接口是跨套间的,那么事实上服务器端是会将接口注册到S的代理接口上是吗?(我对代理和存根不是很明白)如果是就会使情况更复杂,那是不是应该使我的组件与服务器的运行在同一套间中避免使用代理和存根(不考虑远程服务器)?
class R
{
CComObjectGlobal<S> m_sink;
}
公寓1 公寓2
组件A<==>调度dll<=...跨公寓通信(包括跨进程,跨机器)...=>调度dll<====> 组件B如果你在进程1严格遵照自己的公寓规则,进程2严格遵照自己的公寓规则,那中间部分的两个代理dll会自动替你完成复杂但是安全的调度工作。线程公寓本来的目的就是这样。因为你的R跟S总是同一个公寓,所以你只需要让它们互相直接访问就可以了。
NND,害得我好苦啊!给分。