我有一个VB6 COM客户端,它调用进程STA ATL / COM服务器。其中一个服务器方法X可能需要一段时间才能完成,所以我需要能够取消它。我尝试的是在新线程中运行方法代码并包含另一个方法Y,它执行定时WaitForSinleObject。所以客户端首先调用X然后进入一个循环调用VB6 DoEvents然后Y直到Y表示X已经完成。这很好用,但美中不足的是X线程还通过IConnectionPoint接口将事件触发回客户端。事件通过确定但是任何GUI调用都不起作用,因为据我所知,GUI只能在一个线程上工作,即主线程。
使用我现有的代码有明显的方法吗?或者,请您建议其他方法来实现这一目标。
提前致谢。
答案 0 :(得分:1)
您应始终封送您的连接点呼叫。当你不这样做时,你可以调用VB代码,但它以随机方式失败(非编组对象),或者只是不起作用(GUI)。
要使用编组,您必须实现多个接口(见下文)。
另一种可能性是将异步调用转换为VB进行同步'fetch'调用。
所以你的代码来自(在C伪代码中......):
while( !wait( X ) )
{
doevents();
}
到:
while( !wait( X ) )
{
doevents();
fetch_async_data();
}
1)通过将编组添加到COM_AGGRGATE表中,为您的类添加编组:
CComPtr<IUnknown> m_pUnkMarshaler;
BEGIN_COM_MAP(..)
...
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
END_COM_MAP()
2)在FinalConstruct()
中创建编组器FinalConstruct()
{
HRESULT rval = CoCreateFreeThreadedMarshaler( GetControllingUnknown(), &m_pUnkMarshaler.p );
...
}
FinalRelease()
{ ...; m_pUnkMarshaler = 0; }
3)从IConnectionPointImplMT派生您的连接点,并在您可以同时触发多个连接点时在内部锁定调用。
4)不要无限期地等待对象的方法,因为你可以在死锁中运行。
5)对每个暴露的对象和连接点重复此操作。
(这应该有效,但我很长时间没试过......)