开发者

VB6 GUI not working in multithreaded COM environment

I have a VB6 COM client that makes calls to an inprocess STA ATL/COM server. One of the Server methods, X, can take a while to finish so I need to be able to cancel it. What I tried was to run the method code in a new thread and include another method, Y, that does a timed WaitForSinleObject. So the client first calls X then goes into a loop calling VB6 DoEvents and then Y until Y indicates that X has finished. This works fine, however, the fly in the ointment is that the X t开发者_开发知识库hread also triggers events back to the client via the IConnectionPoint interface. The events get through ok but any GUI calls don't work because, as far as I can glean, the GUI can only work on one thread, ie the main thread.

Is there an obvious way round this using my existing code? Alternatively, please can you suggest other ways I could accomplish this.


You should always marshal your connection-point calls. When you don't do that, you can call VB code, but it fails in random ways (non-marshaled-objects), or just doesn't work (GUI).

To use marshaling, you have to implement several interfaces (see below).

The other possibility is to convert the asynchronous calls to VB into synchronous 'fetch' calls.

So your code goes from (in C Pseudo code ...) :

while( !wait( X ) )
{
   doevents();
}

to :

while( !wait( X ) )
{
    doevents();
    fetch_async_data();
}

1) Add a marshaller to your class by adding it to the COM_AGGRGATE table :

CComPtr<IUnknown> m_pUnkMarshaler;

BEGIN_COM_MAP(..)
   ...
   COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
END_COM_MAP()

2) Create the marshaller in FinalConstruct()

FinalConstruct()
{
    HRESULT rval = CoCreateFreeThreadedMarshaler( GetControllingUnknown(), &m_pUnkMarshaler.p );
    ...
}

FinalRelease()
{ ...; m_pUnkMarshaler = 0; }

3) Derive your connection point from IConnectionPointImplMT and lock the calls internally when you can fire more then one at the same time.

4) Do not wait indefinitely in the methods of your object, because you can run in deadlocks.

5) Repeat this for every exposed object and connection point.

(This should work, but I haven't tried this in a long time ...)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜