我有一个VB6 COM客户端,该客户端对进程内STA ATL / COM服务器进行调用。服务器方法之一X可能需要一段时间才能完成,因此我需要将其取消。我试图在一个新线程中运行方法代码,并包含另一个方法Y,该方法执行定时WaitForSinleObject。因此,客户端首先调用X,然后进入循环,依次调用VB6 DoEvents和Y,直到Y指示X已经完成。效果很好,但美中不足的是,X线程还通过IConnectionPoint接口将事件触发回客户端。这些事件顺利进行,但是任何GUI调用都不起作用,因为据我所知,GUI仅可在一个线程(即主线程)上工作。
是否有明显的方法可以使用现有代码解决此问题?或者,请您提出其他可以实现此目标的方法。
您应始终封送连接点呼叫。如果您不这样做,则可以调用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)对每个暴露的对象和连接点重复此操作。
(这应该可行,但是我已经很长时间没有尝试过了……)