Solved

Passing COM object between threads

Posted on 2001-06-07
8
418 Views
Last Modified: 2013-11-20
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
0
Comment
Question by:c095276
8 Comments
 
LVL 3

Expert Comment

by:GlennDean
ID: 6165646
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
 

Author Comment

by:c095276
ID: 6168220
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
 

Author Comment

by:c095276
ID: 6168260
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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
LVL 3

Accepted Solution

by:
GlennDean earned 100 total points
ID: 6168575
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
 

Author Comment

by:c095276
ID: 6168866
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
 
LVL 3

Expert Comment

by:GlennDean
ID: 6168883
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
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6171380
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
 
LVL 23

Expert Comment

by:Roshan Davis
ID: 9484584
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

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
The purpose of this video is to demonstrate how to set up the WordPress backend so that each page automatically generates a Mailchimp signup form in the sidebar. This will be demonstrated using a Windows 8 PC. Tools Used are Photoshop, Awesome…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

815 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now