3
votes

I have a multi-threaded C++Builder GUI app, which communicates with a third-party app via COM.

I need to call methods of the COM object from several threads, and I'm protecting access with a mutex. Apparently, the main GUI thread must use STA model, but my worker threads need to use MTA. The COM object is constructed in an MTA thread.

Everything works fine except access to the COM object from the GUI thread, due to the MTA/STA mismatch.

I've read a bit about marshalling, but haven't tried to implement it, because the examples I've seen seem to require different access semantics depending the the current apartment model, and I really would like to have code that (from a programmer's POV) doesn't care about the current apartment model.

So, is there an idiomatic way to write COM code that operates on the 'same' object, but can be called from both STA and MTA threads?

1
Marshaling the interface pointer is required, you cannot skip it. IGlobalInterfaceTable makes it easy.Hans Passant
@Hans, yes, but if I have it right, some threads need the marshalled pointer, others need the unmarshalled one? I'm looking for a way to unify that or dynamically switch which interface pointer depending on current thread apartment model...?Roddy
Well, just always marshal the pointer. You just get the original back if no apartment transition is required.Hans Passant
@Hans, how is Roddy supposed to accept the answer if you put it in comments? :-) This question is listed as unanswered.Euro Micelli

1 Answers

2
votes

Put the COM object interface into the Global Interface Table and let the GIT handle the marshalling for you. When any thread requests the COM interface, the GIT checks the calling apartment and will provide a direct pointer or a suitable proxy accordingly. Your code won't know the difference (or care), just use the returned interface normally as needed.

This is documented on MSDN:

Accessing Interfaces Across Apartments