有这样一个怪事,我将自己的组件注册到一个进程外组件的连接点上,以得到他发出的A事件。可是那个进程外服务器(exe程序)关掉后悄无声息,没有通知我,因此在我的程序退出前在注消事件时发生异常,Unadvise 返回值为"0x800706ba",这样我的组件就不能释放,导致我的程序不能退出,窗口己关闭但在任务管理器中可见。不知如何解决,急急急!!!!

解决方案 »

  1.   

    Unadvise失败?
    你应该确定服务器在客户Unadvise之前不能被关闭
      

  2.   

    可事实是他的确是在Unadvise 之前就己经关闭了,而且还保存着我的组件的一个引用。我无法确保那个exe 不能被关闭。
      

  3.   

    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.
      

  4.   

    to phiger 
    难道这是唯一的解决办法吗?还有没有更好的办法?与我要实现的功能类似的一个程序就没有出现我所遇到的问题,但是我没搞懂。
      

  5.   

    在服务器端,ATL的IConnectionPoint::Advise()的实现代码对客户添加了一个讨厌的AddRef(),其目的是除非你显式调用Unadvise(),否则,连接点的两端都不能释放。
    如果服务器突然死亡,对连接点客户端的调用无法释放,所以你的组件也不能释放。解决的办法是连接点客户端的实现不能采用普通的IUnknown实现(即CComObject的实现),然它的AddRef()以及Release()什么都不做,例如,ATL::IDispEventImpl就是这样做的。
    如果你从一般的ATL Class中派生自事件接口,肯定是不行的,因为最终的子类是CComObject,它的AddRef(),Release()会覆盖子类的实现。较好的办法是把Sink对象作为一个单独的对象,并且它的AddRef(),Release()什么也不做,然后它跟客户端的其它对象可以用指针来联系。
      

  6.   

    to arxing:
        正如你说的,在我所看的另一个代码中确实是做了一个影子组件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的代理接口上是吗?(我对代理和存根不是很明白)如果是就会使情况更复杂,那是不是应该使我的组件与服务器的运行在同一套间中避免使用代理和存根(不考虑远程服务器)?
      

  7.   

    既然我说了CComObject<>实现回调对象会增加额外引用,你就不要用CComObject<>了。如果你连三个简单的方法都懒得写,可以用CComObjectGlobal<>代替。
    class R
    {
      CComObjectGlobal<S> m_sink;
    }
      

  8.   

    另外,跨进程的两方肯定属于不同的套间,肯定需要代理存根,所以没有你说的增加负担的情况。
    公寓1                                                   公寓2
    组件A<==>调度dll<=...跨公寓通信(包括跨进程,跨机器)...=>调度dll<====> 组件B如果你在进程1严格遵照自己的公寓规则,进程2严格遵照自己的公寓规则,那中间部分的两个代理dll会自动替你完成复杂但是安全的调度工作。线程公寓本来的目的就是这样。因为你的R跟S总是同一个公寓,所以你只需要让它们互相直接访问就可以了。
      

  9.   

    问题解决了,安装了MS IE6的 SP1 后我又可以收到那两个关键的事件了,原来是MS的BUG!!
    NND,害得我好苦啊!给分。