Passing COM object between threads

I have a COM object that was written in VB which I use in a VC++ app.  I am passing a pointer to the object between two threads.  The creating thread uses a new to create the thread, calls the objects CreteaDispatch as so  someCOMMObj->CreateDispatch( CLSID_SOMECLASS), and calls some of the objects function in order to initialize it.  This all works fine.  I pass the object as shown below

AfxBeginThread(SomeThread::InquiryThreadProc, someCOMObj);

SomeThread receives the pointer properly, which means that I have looked at the address and know that they are the same.  I then call CoInitialize( NULL) from the receiving thread, but when I go to call any function of the Com object an exception of some type is thrown.  It is not a COleDispatchException *, or CException * I am explicitly catching those.  What could be going on?  Is there any way that I can tell wat the exception is that is being thrown?

Thanks
c095276Asked:
Who is Participating?
 
GlennDeanConnect With a Mentor Commented:
What I mean is the standard COM marshaller (i.e. oleaut32.dll) can't (to the best of my knowledge) marshall arbitrary interface pointers around.  It can only marshall IUnknown * and IDispatch * from client to server and vice versa.  
   What I was thinking you should try is this: let's say you wanted to pass IMyInterface * pMyInt to a client.  Then go
IUnknown * pUnk;
pMyInt->QueryInterface(IID_IMyInterface,(void **)&pUnk);

Then pass pUnk to client.  

In the client, query for the interfaces it needs (say they are IMyInterface and IMySecondInterface):
IMyInterface * pMyInt;
IMySecondInterface * pMySecInt;
pUnk->QueryInterface(IID_IMyInterface,(void **)&pMyInt);
pUnk->QueryInterface(IID_IMySecondInterface,(void **)&pMySecInt);

I'm not sure the above will work (I do the above when the client and the server are both COM objects) since you will be passing pUnk to a thread.  

Also, don't forget to call CoInitialize inside the thread.

   Glenn
0
 
GlennDeanCommented:
I wouldn't pass someCOMObj, but rather IUnknown * and let the thread query for whatever interface it needs.  Something like

AfxBeginThread(SomeThread::InquiryThreadProc, (LPVOID)someCOMObj->GetControllingUnknown());

0
 
c095276Author Commented:
I have not had a chance to try your suggestion yet Glenn, but I did discover something else.  I did a CoInitialize( NULL) and a CreateDispatch on each thread as I passed the object around.  This time I recieved a CException error that says, "The application called an interface that was marshalled for a different thread."  Will your suggestion still work or is it something else?

Thanks

0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
c095276Author Commented:
Glenn,
  What do you mean by "let the thread query for whatever interface it needs."  Could you show me some code on the receiving side, that is the UINT SomeThread::InquiryThreadProc( LPVOID pParam) function, on how to handle the IUnknown pointer.

Thanks again
0
 
c095276Author Commented:
I discovered that the CoInitialize works on an apartment thread model.  I assume that I need more of a free threading model, so I was going to switch to CoInitializeEx and specify COINIT_MULTITHREADED.  When I compile I receive an error, "'CoInitializeEx' : undeclared identifier"  The header file objbase.h includes this function but it is defined only if
(_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)

What is the right way to specify these preprocessor directives?  Are they specifed in the project settings?
0
 
GlennDeanCommented:
I've run into that problem many times.  I just add _WIN32_DCOM to my preprocessor defines (i.e Project -> Settings -> C/C++ tab, Category = Preprossor, Preprocessor defines edit box) and everything works fine.

  Glenn
0
 
ShaunWildeCommented:
since your componant is VB I think it is apartment only - so to marshal it between apartments you should use (ready for this is its a biggie)

CoMarshalInterThreadInterfaceInStream(...) - to marshal the pointer to a stream

CoGetInterfaceAndReleaseStream(...) - to get it from the stream

this technique and others are demonstrated in the following MS KB article http://support.microsoft.com/support/kb/articles/Q206/0/76.ASP
0
 
Roshan DavisCommented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered by : GlennDean, ShaunWilde (points to be split)

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Roshan Davis
EE Cleanup Volunteer
0
All Courses

From novice to tech pro — start learning today.