1

我有一个调用进程内 STA ATL/COM 服务器的 VB6 COM 客户端。服务器方法之一,X,可能需要一段时间才能完成,所以我需要能够取消它。我尝试的是在新线程中运行方法代码并包含另一个方法 Y,它执行定时 WaitForSinleObject。因此,客户端首先调用 X,然后进入一个调用 VB6 DoEvents 的循环,然后是 Y,直到 Y 指示 X 已经完成。这很好用,但美中不足的是 X 线程还通过 IConnectionPoint 接口将事件触发回客户端。事件顺利通过,但任何 GUI 调用都不起作用,因为据我所知,GUI 只能在一个线程上工作,即主线程。

使用我现有的代码有没有明显的方法来解决这个问题?或者,请您建议我可以完成此任务的其他方法。

4

1 回答 1

1

您应该始终编组您的连接点调用。如果不这样做,您可以调用 VB 代码,但它会以随机方式失败(非编组对象),或者根本不起作用(GUI)。

要使用编组,您必须实现几个接口(见下文)。

另一种可能性是将对 VB 的异步调用转换为同步的“获取”调用。

所以你的代码来自(在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) 对每个暴露的对象和连接点重复此操作。

(这应该可以,但是我很久没有尝试过了......)

于 2009-10-12T16:47:01.927 回答