|Answer from Bio :
Here are my thoughts concerning why "A" worked while "B" did not :
1. The fact that "A" and "B" are both marked in the registry as
"ThreadingModel=Apartment" indicates that they are both STA (Single-Threaded
2. Now, for both "A" and "B", the whole idea behind making them STA objects
is to ensure their thread safety without having to use additional
thread-synchronization code. However, as you have explained, you have already
personally ensured that no two threads access them at any time.
3. Therefore, as far as "A" is concerned, passing a direct pointer to it to
other threads and then calling its methods from those threads, while
technically unsound, did not pose any danger. You -have- broken the rules.
But the rules were not needed anyway.
4. If you had marshalled "A" across to thread 3 and thread 4, thread 3 and
thread 4 will not receive a direct pointer to "A". They will instead each
receive a proxy to "A". Method calls to "A" will have to go through the
marshalling process and a private message will be sent to the message loop of
thread 2 (the thread which created "A") which will eventually result in the
execution of the method.
5. Point 4 entails some performance penalties as you can imagine. In fact,
since you have ensured that no two threads will ever touch "A" at anytime,
"A" is technically a Free-Threaded Object.
6. Now, on to "B". You mentioned that "B" is written in VB. This can be
significant. Because STA objects have the advantage of thread-affinity, VB
uses thread-local storage (TLS) to store various state information on
VB-generated COM objects. The thread whose local storage is used is the
thread of the STA in which the COM object lives in and is also the one which
7. Using these VB-generated COM objects from an external thread without
marshalling is thus fatal. They will not be able to access information stored
inside their TLS.
Hope the above helps.
PS : just curious : Did you transport the interface pointer from thread to
thread via thread parameters ?